591 Commits

Author SHA1 Message Date
Râu Cao
0f3b9f176e 0.8.1
All checks were successful
continuous-integration/drone/push Build is passing
2023-09-03 15:35:46 +02:00
822ae2f945 Merge pull request 'Fix migration failing with PostgreSQL' (#145) from bugfix/144-postgres_migration into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #145
2023-09-03 13:32:36 +00:00
Râu Cao
96c669ab4e Update database schema, fix spec
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Release Drafter / Update release notes draft (pull_request) Successful in 2s
2023-09-03 15:29:09 +02:00
Râu Cao
558100c35e Fix migration failing with PostgreSQL 2023-09-03 15:28:32 +02:00
Râu Cao
6739b38f4c 0.8.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-09-01 12:18:26 +02:00
7e1272c936 Merge pull request 'Service pages for Chat and Social' (#143) from feature/service_pages into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #143
Reviewed-by: galfert <garret.alfert@gmail.com>
2023-09-01 08:36:09 +00:00
Râu Cao
ecdeb4c122 Fix copypasta
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Release Drafter / Update release notes draft (pull_request) Successful in 3s
2023-09-01 10:32:11 +02:00
Râu Cao
8614e2f12b Use service configs on dashboard
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Only show enabled services, and use the URLs from the various configs.
2023-08-13 17:24:10 +02:00
Râu Cao
a038a857d9 Make Drone CI configurable 2023-08-13 17:23:57 +02:00
Râu Cao
eee81d0cf1 Small link improvement
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-08-13 15:41:57 +02:00
Râu Cao
b7fa4b012a Allow Mastodon address domain to be different from primary domain
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-08-13 12:27:05 +02:00
Râu Cao
10bcd5c32b Ignore .env.development 2023-08-13 12:26:56 +02:00
Râu Cao
f79d5d4724 Use select element instead of tabs on mobile
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-08-11 14:17:12 +02:00
Râu Cao
866ffbe615 Upgrade tailwindcss-stimulus-components to latest version
All checks were successful
continuous-integration/drone/push Build is passing
The latest one offers more tabs features. Required some changes to the
modals and tabs code.
2023-08-11 13:58:57 +02:00
Râu Cao
3c1fe3396d Add Mastodon service page 2023-08-11 13:58:53 +02:00
Râu Cao
e4242333d9 Add recommended apps for Chat/XMPP
All checks were successful
continuous-integration/drone/push Build is passing
2023-08-08 19:59:29 +02:00
Râu Cao
138f13c1a0 Add note
All checks were successful
continuous-integration/drone/push Build is passing
2023-08-07 18:16:40 +02:00
Râu Cao
ad5e515200 Update README 2023-08-07 18:16:34 +02:00
Râu Cao
1ea8b22a59 WIP Add service page for Chat
Some checks are pending
continuous-integration/drone/push Build is running
2023-08-07 18:16:14 +02:00
Râu Cao
f49aff262c Add base controller for service controllers
Some checks are pending
continuous-integration/drone/push Build is running
2023-08-07 18:15:17 +02:00
852e2fea1e Merge pull request 'remoteStorage OAuth' (#109) from feature/rs-oauth into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #109
2023-08-04 08:55:28 +00:00
Râu Cao
353b55fe1a Add RS OAuth controller specs
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Release Drafter / Update release notes draft (pull_request) Successful in 3s
2023-08-01 14:29:24 +02:00
Râu Cao
ba0cbba96b Add feature spec for RS OAuth dialog
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-08-01 13:01:41 +02:00
Râu Cao
5f921f1b53 RS OAuth pre-fills username for login 2023-08-01 13:01:03 +02:00
Râu Cao
a2d27bf575 Support pre-filling of username in login form 2023-08-01 13:00:22 +02:00
Râu Cao
fcf9a065e1 Fix specs
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-07-14 15:56:28 +02:00
Râu Cao
ec9bcacd46 Add specs for RemoteStorageAuthorization model
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
2023-07-14 15:31:20 +02:00
Râu Cao
645abac810 Rename RS token expiry job 2023-07-14 15:29:29 +02:00
Râu Cao
e11be727a1 Indentation 2023-07-14 15:29:04 +02:00
Râu Cao
12b24337e7 Fix typo 2023-07-14 15:28:45 +02:00
Râu Cao
b0bfc290c4 Refactor code for newer Redis 2023-07-14 15:28:09 +02:00
Râu Cao
4c6c81171b Fix typo 2023-07-14 15:27:57 +02:00
Râu Cao
4d88a40109 Add separate config for RS Redis 2023-07-14 15:27:30 +02:00
Râu Cao
d9b39b36fb Merge branch 'master' into feature/rs-oauth
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-07-13 15:31:28 +02:00
Râu Cao
06aed8c33d Count up minor version on feature merge
All checks were successful
continuous-integration/drone/push Build is passing
2023-07-13 15:26:35 +02:00
0a778e92d8 Merge pull request 'Add modal component, QR codes for invite links' (#140) from feature/139-qr_codes into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #140
2023-07-13 13:24:12 +00:00
Râu Cao
e5a5633e44 Add Redis config for dev with Redis on localhost
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-07-04 17:00:04 +02:00
Râu Cao
a68825493f Add Redis config in CI
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-07-04 16:44:11 +02:00
Râu Cao
e1e83386a8 Merge branch 'master' into feature/rs-oauth 2023-07-04 16:43:32 +02:00
Râu Cao
3adc1917f6 Improve outline button style, use everywhere
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Release Drafter / Update release notes draft (pull_request) Successful in 4s
2023-06-27 19:23:20 +02:00
Râu Cao
8a570ce724 Use modal component for LndHub setup code 2023-06-27 19:23:20 +02:00
Râu Cao
c78df9e5f1 Add QR code icon, button, modal for invites
Using https://excid3.github.io/tailwindcss-stimulus-components/
2023-06-27 19:23:20 +02:00
5c2df3df07 Add Redis service to Drone config
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
2023-06-27 15:07:28 +02:00
83e3e2ecd8 Merge pull request 'Allow editing and resetting of all admin setting strings' (#137) from feature/admin_settings into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #137
Reviewed-by: greg <greg@noreply.kosmos.org>
2023-06-24 14:57:08 +00:00
b32e2fcb7b Merge pull request 'Fix docker volume mappings for node_modules, improve docker-compose usage' (#138) from bugfix/fix-docker-mapping into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #138
Reviewed-by: raucao <raucao@noreply.kosmos.org>
2023-06-23 15:38:30 +00:00
96a4db5bae improve sentence
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Release Drafter / Update release notes draft (pull_request) Successful in 4s
2023-06-23 17:32:39 +02:00
c7925f132e formatting
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-06-23 17:30:00 +02:00
e4406bf6ff use PRIMARY_DOMAIN for both web and sidekiq directives 2023-06-23 17:29:42 +02:00
ee7769c8c7 Update readme with simplified usage
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-06-23 17:21:52 +02:00
fdf3218f88 leave services uncommented, add /akkounts/node_modules to volume mapping as a directory to explicitly exclude 2023-06-23 17:21:43 +02:00
652ed5f7e3 copy files as list 2023-06-23 17:21:17 +02:00
Râu Cao
e4ed797920 Adjust specs
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Release Drafter / Update release notes draft (pull_request) Successful in 3s
2023-06-22 13:57:55 +02:00
Râu Cao
93740f17ef Allow editing and resetting of all admin setting strings
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
2023-06-22 13:48:29 +02:00
Râu Cao
affb058671 Add config for XMPP notifications from-address 2023-06-21 16:44:06 +02:00
Râu Cao
6acc3f2f59 0.7.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-06-20 18:49:38 +02:00
7987e92723 Merge pull request 'Offer LNURL QR code for download on Lightning info page' (#135) from feature/lightning_donation_qr_codes into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #135
Reviewed-by: slvrbckt <slvrbckt@noreply.kosmos.org>
Reviewed-by: bumi <bumi@noreply.kosmos.org>
2023-06-20 16:44:58 +00:00
Râu Cao
d922e7f869 Resolve review comment
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Release Drafter / Update release notes draft (pull_request) Successful in 3s
2023-06-20 18:18:14 +02:00
716d4b944a Merge branch 'master' into feature/rs-oauth
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
# Conflicts:
#	app/models/user.rb
#	config/routes.rb
#	db/schema.rb
2023-06-20 14:07:46 +02:00
42af148168 Persist RS auth tokens in Redis 2023-06-20 14:02:48 +02:00
Râu Cao
89c67f3617 Merge branch 'master' into feature/lightning_donation_qr_codes
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-06-18 15:51:38 +02:00
1b959b5643 Merge pull request 'Let users add a verified nostr pubkey to their account' (#101) from feature/98-nostr_nip05 into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #101
2023-06-16 13:04:24 +00:00
Râu Cao
4551a14362 Fix path
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Release Drafter / Update release notes draft (pull_request) Successful in 4s
2023-06-16 14:55:11 +02:00
Râu Cao
bfc0969829 Improve wording
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
2023-06-16 14:39:28 +02:00
Râu Cao
a1be338ba1 Add hint for updating nostr profiles when pubkey is added 2023-06-16 14:39:26 +02:00
Râu Cao
589e46bc63 Replace hardcoded domains with primary domain setting 2023-06-16 14:38:04 +02:00
Râu Cao
34e4cec503 Add NIP-05 well-known endpoint 2023-06-16 14:37:16 +02:00
Râu Cao
c48538a1c6 Add primary domain setting 2023-06-16 14:37:15 +02:00
Râu Cao
2cced696f5 Don't try to access target when it doesn't exist 2023-06-16 14:35:57 +02:00
Râu Cao
beaafa5d7e Make nostr pubkey unique globally 2023-06-16 14:35:56 +02:00
Râu Cao
9cf309aaa8 Prevent mounting of checked-in vendored files
Mount bundle cache specifically on `vendor/cache` instead of all of
`vendor`, which prevents access to vendored javascript code for example.
2023-06-16 14:34:34 +02:00
Râu Cao
e8bbe6c713 Let user remove nostr pubkey from account 2023-06-16 14:34:32 +02:00
Râu Cao
49de4007ab Settings page for adding verified nostr pubkeys 2023-06-16 14:22:30 +02:00
Râu Cao
bc4d9ff528 Add nostr_pubkey to users 2023-06-16 13:52:42 +02:00
Râu Cao
b03c6e9513 Support vendoring npm module code 2023-06-16 13:51:09 +02:00
Râu Cao
332ad757a5 Use respond_to for request formats
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-06-13 12:30:38 +02:00
Râu Cao
07fe8dba71 Add a copy button for the Lightning address
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Same as on profile settings page.
2023-06-12 18:18:47 +02:00
Râu Cao
aedaabc7ba Offer lnurl-pay QR codes for download on the Lightning page 2023-06-12 18:18:06 +02:00
Râu Cao
8eb5f093a4 Don't show flash message when opening the root URL while signed out 2023-06-08 08:04:23 +03:00
de45d070aa Merge pull request 'Report Lndhub API errors to Sentry' (#133) from refactor/lndhub_integration into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #133
2023-06-06 15:44:36 +00:00
c0b1112e49 Merge pull request 'Hide unsuccessful outgoing lndhub txs in list' (#132) from bugfix/lndhub_tx_list into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #132
2023-06-06 15:43:38 +00:00
Râu Cao
2f90393eb6 Lndhub v2 service inherits from v1, only adds v2-specific code
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Release Drafter / Update release notes draft (pull_request) Successful in 3s
2023-06-05 13:53:24 +03:00
Râu Cao
8b87072485 Raise custom auth error, re-raise on failed re-auth 2023-06-05 13:52:41 +03:00
Râu Cao
82019f47be Report lndhub errors to Sentry 2023-06-05 13:51:59 +03:00
Râu Cao
259e72167b Hide unsuccessful outgoing lndhub txs in list
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Release Drafter / Update release notes draft (pull_request) Successful in 4s
2023-06-05 13:06:49 +03:00
Râu Cao
7000908891 Auto-login Discourse link
All checks were successful
continuous-integration/drone/push Build is passing
2023-06-04 15:15:09 +03:00
Râu Cao
df0c13b400 Fix potential nil access
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-31 14:43:00 +02:00
Râu Cao
387a2fa2e6 0.6.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-31 14:12:26 +02:00
68eba80fd7 Merge pull request 'Integrate Discourse Connect (SSO)' (#131) from feature/126_discourse_sso into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #131
2023-05-31 10:02:43 +00:00
Râu Cao
7e05530ab7 Add specs for Discourse Connect
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Release Drafter / Update release notes draft (pull_request) Successful in 3s
2023-05-31 12:00:33 +02:00
Râu Cao
745a319b3d Minor refactoring 2023-05-31 12:00:31 +02:00
Râu Cao
f829bb3379 Use devise method for requiring login 2023-05-31 12:00:02 +02:00
Râu Cao
19bafe081f Integrate Discourse Connect (SSO) 2023-05-31 12:00:02 +02:00
d130f2f68b Merge pull request 'Allow users to set/update their display name in LDAP' (#128) from feature/123-display_names into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #128
Reviewed-by: greg <greg@noreply.kosmos.org>
2023-05-31 09:13:50 +00:00
Râu Cao
e284996c1c Remove obsolete route
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Release Drafter / Update release notes draft (pull_request) Successful in 4s
2023-05-28 15:28:51 +02:00
Râu Cao
51489a83ab Use feature block for email update specs
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-05-28 15:25:53 +02:00
Râu Cao
05426e4ced Add specs for display name update 2023-05-28 15:25:42 +02:00
Râu Cao
445cdfa024 Only validate display name when updated
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Otherwise we needlessly fetch the validated one from LDAP every time a
model is saved.
2023-05-27 20:11:01 +02:00
Râu Cao
f74227fedb Allow users to set/update their display name in LDAP
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
2023-05-27 19:59:49 +02:00
Râu Cao
32d1992632 Set user instance var for settings routes where needed 2023-05-27 19:58:59 +02:00
48be35f1b1 Merge pull request 'Allow updating one's email address on the account settings page' (#127) from feature/103-update_email into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #127
Reviewed-by: greg <greg@noreply.kosmos.org>
2023-05-26 18:07:07 +00:00
87720ef285 Merge pull request 'Add feature flags' (#125) from feature/124-feature_flags into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #125
Reviewed-by: greg <greg@noreply.kosmos.org>
2023-05-26 17:56:50 +00:00
Râu Cao
193a4c2edd Remove obsolete function argument
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Release Drafter / Update release notes draft (pull_request) Successful in 4s
2023-05-25 19:31:16 +02:00
Râu Cao
134c81460a Allow email address updates on account settings page
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-05-25 16:58:53 +02:00
Râu Cao
b1a693e7cf Send different Devise mail for re-confirmations 2023-05-25 16:58:45 +02:00
Râu Cao
75bd879f84 Rename settings menu item for Lightning 2023-05-25 16:57:14 +02:00
Râu Cao
33a9e1eaa9 Use username instead of email in Devise mails 2023-05-25 16:56:40 +02:00
Râu Cao
7b321577db Update LDAP mail attribute when re-confirming email 2023-05-25 16:55:27 +02:00
Râu Cao
61f12c2741 Improve form fields with errors for model updates 2023-05-25 16:53:16 +02:00
Râu Cao
c58358c66e Add feature flags, RS dashboard dummy
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Release Drafter / Update release notes draft (pull_request) Successful in 4s
closes #124
refs #94
2023-05-23 19:18:11 +02:00
Râu Cao
287adbd365 Add flipper gem and database migration/tables 2023-05-23 14:09:35 +02:00
Râu Cao
9048052318 Fix URL in email template
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-16 13:22:44 +02:00
cddc1e86f6 Merge pull request 'Show fees of Lightning transactions' (#122) from feature/lightning_fees into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #122
Reviewed-by: hueso <hueso@noreply.kosmos.org>
Reviewed-by: bumi <bumi@noreply.kosmos.org>
2023-05-10 12:27:24 +00:00
Râu Cao
ce7387a409 Remove obsolete routes
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Release Drafter / Update release notes draft (pull_request) Successful in 6s
2023-05-03 21:54:33 +02:00
Râu Cao
f1ae5667de Shape tx details UI a bit
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-05-03 12:51:22 +02:00
Râu Cao
67a9fc02d7 Rename Wallet to Lightning Network, move to Services
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-05-01 16:13:41 +02:00
Râu Cao
34849b28b0 WIP show fees of Lightning transactions 2023-05-01 15:15:23 +02:00
8ce5f9708f Merge pull request 'Add configurable default chatroom bookmarks for new users' (#116) from feature/default_chatrooms into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #116
Reviewed-by: galfert <garret.alfert@gmail.com>
2023-04-19 13:07:00 +00:00
Râu Cao
cb2197893c Merge branch 'master' into feature/default_chatrooms
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Release Drafter / Update release notes draft (pull_request) Successful in 4s
2023-04-18 17:00:48 +02:00
Râu Cao
dabd892a25 Improve RS OAuth UI
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-04-13 16:21:48 +02:00
Râu Cao
eeabbdb7df Merge branch 'master' into feature/rs-oauth
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-04-13 15:02:51 +02:00
7a50bd23d6 Merge pull request 'Add user preferences and configurable notifications' (#113) from feature/user_preferences into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #113
Reviewed-by: galfert <garret.alfert@gmail.com>
2023-04-11 21:04:46 +00:00
64c8c3cb06 Merge pull request 'WebFinger endpoint' (#118) from feature/webfinger into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #118
Reviewed-by: raucao <raucao@noreply.kosmos.org>
2023-04-11 09:44:39 +00:00
Râu Cao
a2100b23a9 Formatting, wording
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Update release notes draft
2023-04-11 11:41:30 +02:00
27195f693a Merge pull request 'Fix failing spec expectation when using Ruby 3.x' (#119) from fix/ruby-3-failed-expectation into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #119
Reviewed-by: raucao <raucao@noreply.kosmos.org>
2023-04-11 09:32:46 +00:00
9e74c89a80 Fix failing spec expectation when using Ruby 3.x
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Update release notes draft
2023-04-10 23:03:59 +02:00
0774c88918 WebFinger endpoint
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-04-10 21:23:21 +02:00
ef2d2b6422 Merge pull request 'Add remoteStorage settings' (#117) from feature/rs-settings into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #117
Reviewed-by: raucao <raucao@noreply.kosmos.org>
2023-04-09 09:45:19 +00:00
a47e4fc16b Add RS storage URL to test env
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Update release notes draft
2023-04-09 10:12:12 +02:00
9b89101afc Basic RemoteStorage settings
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
2023-04-08 21:49:16 +02:00
Râu Cao
ad90fcd539 Add specs for xmpp default bookmarks, refactor xmpp job usage
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-04-08 16:37:21 +02:00
Râu Cao
705bd63b42 Add configurable default room bookmarks for new users
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-07 23:03:43 +02:00
Râu Cao
83e418cdee Update README
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-07 20:11:45 +02:00
Râu Cao
7a193d6647 Add comment
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-06 16:25:01 +02:00
Râu Cao
bb82b6b462 Update README 2023-04-06 16:24:46 +02:00
Râu Cao
4e2e13108c Refactor user preferences, add defaults from file
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Update release notes draft
* Turn prefs into a flat hash structure, since nesting is not worth the
trouble
* Add a custom serializer class for prefs
* Add a config file for defaults and merge set prefs with unset ones
* Use booleans for "true" and "false", and integers where appropriate
2023-04-05 17:02:35 +02:00
Râu Cao
ca7475dca2 Add notification mailer, make wallet notifications configurable
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-04-04 13:39:32 +02:00
Râu Cao
43a43e1a2c Use setting instead of ENV var
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-04 12:46:09 +02:00
Râu Cao
595bb03c5a Do not exchange XMPP contacts when turned off by inviter
Some checks are pending
continuous-integration/drone/push Build is running
2023-04-04 12:45:13 +02:00
Râu Cao
62cd0eb7d1 Re-rename "ejabberd" service to "xmpp"
Shouldn't matter which implementation is integrated if someone adds
another one
2023-04-04 12:29:39 +02:00
Râu Cao
f19baaf22a Add new user settings pages for Chat and Wallet 2023-04-04 12:28:53 +02:00
Râu Cao
23821f9e65 Add preferences to user model 2023-04-04 12:27:49 +02:00
Râu Cao
a33410eeb4 Allow handing custom field names to toggle fieldset component 2023-04-04 12:03:00 +02:00
Râu Cao
a1b238e86b Fix email default URL options missing
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-04 09:11:06 +02:00
Râu Cao
334b47353e WIP Add notifications preferences page
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-03 13:55:58 +02:00
Râu Cao
6848bd739c Add horizontal layout option for fieldset component 2023-04-03 13:55:39 +02:00
Râu Cao
7f77ad5528 Refactor user settings
All checks were successful
continuous-integration/drone/push Build is passing
Use resources instead of custom controllers, following the Rails way
and making things much cleaner in the process.
2023-04-03 13:19:07 +02:00
6f2160b479 Merge pull request 'Add solargraph in development, document usage with bundled gems' (#112) from feature/solargraph into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #112
2023-04-02 08:19:26 +00:00
Râu Cao
f08bb56a7a 0.5.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-01 11:44:25 +02:00
Râu Cao
fe1dfd8ec8 Add solargraph in development, document usage with bundled gems
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Update release notes draft
2023-03-31 18:07:38 +02:00
c1f275463e Merge pull request 'Add Redis, Sidekiq to Docker Compose setup' (#110) from feature/docker-compose_sidekiq into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #110
Reviewed-by: galfert <garret.alfert@gmail.com>
2023-03-31 09:09:46 +00:00
324809f77e Merge pull request 'Expire inactive sessions, optionally allow to stay signed in' (#82) from feature/8-session_timeouts into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #82
Reviewed-by: galfert <garret.alfert@gmail.com>
2023-03-31 07:58:24 +00:00
Râu Cao
f9b07bcb01 Use development branch of release drafter action
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-28 17:27:31 +02:00
Râu Cao
986eb5387c Use release drafter fork with PR ID fix
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-28 17:13:39 +02:00
f76e2c2f14 Merge pull request 'Add Gitea Release Drafter as Gitea Action' (#111) from feature/release_drafter into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #111
2023-03-28 14:21:44 +00:00
Râu Cao
22a7bbe6eb Add Gitea Release Drafter as Gitea Action
All checks were successful
Update release notes draft
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-03-28 16:17:19 +02:00
18f4deb30f Merge pull request 'Add (optional) Sentry integration' (#108) from feature/sentry_integration into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #108
Reviewed-by: greg <greg@noreply.kosmos.org>
2023-03-28 12:53:00 +00:00
Râu Cao
9f9bf6fd80 Add Redis and Sidekiq to Docker Compose setup
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Update release notes draft
2023-03-28 12:24:58 +02:00
Râu Cao
d2987da70a Send Devise emails via Sidekiq 2023-03-28 12:22:17 +02:00
Râu Cao
6b7a80e23a Make Redis URL configurable 2023-03-28 12:21:54 +02:00
Râu Cao
42b9b27561 Allow external network access
All checks were successful
continuous-integration/drone/push Build is passing
Useful for connecting to services on private networks for example.
2023-03-28 11:38:56 +02:00
Râu Cao
c17c980b69 Prepare for multiple akkounts containers
All checks were successful
continuous-integration/drone/push Build is passing
Initially "web" and "sidekiq"
2023-03-28 11:25:10 +02:00
ee42d68471 Add RemoteStorageAuthorization model
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-03-28 01:21:28 +02:00
7acc3b2106 RemoteStorage OAuth dialog 2023-03-28 01:21:28 +02:00
20c014607c Basic RemoteStorage settings 2023-03-27 22:52:01 +02:00
Râu Cao
f199d5d12a Add (optional) Sentry integration
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
A Sentry DSN can be set via `SENTRY_DSN` and authenticated users will be
tagged with ID and username (cn) in events.
2023-03-27 12:47:28 +02:00
Râu Cao
4b17afa93d Fix typo
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-27 11:55:02 +02:00
Râu Cao
6d52af53ae Add basic storage config
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-27 11:46:39 +02:00
Râu Cao
4c5ad67652 Require action_mailbox
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-27 11:40:59 +02:00
Râu Cao
3437a756eb Only create LNDHub accounts when feature is enabled
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-24 16:01:53 +07:00
0d9fc4aa74 Merge pull request 'Make email settings configurable, add custom mailer for one-off emails' (#107) from feature/custom_mailer into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #107
Reviewed-by: greg <greg@noreply.kosmos.org>
2023-03-23 15:52:43 +00:00
82475161a9 Merge branch 'master' into feature/custom_mailer
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-03-23 15:38:43 +00:00
Râu Cao
fb3b9af3e5 Add custom mailer for one-off emails
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-03-22 14:54:23 +07:00
Râu Cao
b1a0268e6b Make email settings configurable 2023-03-22 14:53:44 +07:00
e1e7d8f87d Merge pull request 'Move exchanging of XMPP contacts to account confirmation' (#105) from chore/exchange_xmpp_contacts_after_confirmation into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #105
Reviewed-by: galfert <garret.alfert@gmail.com>
2023-03-22 06:45:30 +00:00
Râu Cao
5b46f3adf5 Move exchanging of XMPP contacts to account confirmation
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Since the ejabberd service is now being enabled after the confirmation,
we also need to move the exchanging of roster contacts to that point.
2023-03-20 17:59:43 +07:00
Râu Cao
a8a8fba14c Change styling of Devise shared links
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Update release notes draft
2023-03-19 18:07:09 +07:00
Râu Cao
8a7016a30b Add remember-me function for sign-in
When checked, remember user for 2 weeks. Otherwise expire session after
30 minutes.
2023-03-19 18:06:18 +07:00
Râu Cao
e2618de7c6 Add time limit for inactive sessions
closes #8
2023-03-19 16:16:36 +07:00
90680368fb Merge pull request 'Complete admin pages for service settings' (#104) from feature/admin_user_service_settings into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #104
Reviewed-by: galfert <garret.alfert@gmail.com>
2023-03-19 06:33:13 +00:00
Râu Cao
8d90847896 Add setting for contact roster name
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
And only exchange contacts when ejabberd integration is enabled
2023-03-15 09:03:39 +00:00
Râu Cao
8da297811b Mark settings as readonly, allow params for editable ones 2023-03-15 09:03:39 +00:00
Râu Cao
fa56d6b772 Refactor toggles to work without JS, add specs 2023-03-15 09:03:39 +00:00
Râu Cao
ca1221e9f3 Refactor admin settings, add all service settings 2023-03-15 09:03:39 +00:00
Râu Cao
295d486761 Disable toggles on admin user page
They are purely informational
2023-03-15 09:03:39 +00:00
Râu Cao
e00390d102 Add cached settings for all current services 2023-03-15 09:03:39 +00:00
Râu Cao
b947480190 Refactor sidenav link component, allow multiple levels 2023-03-15 09:03:39 +00:00
Râu Cao
fa07978aac Add form field update capability to toggle components 2023-03-15 09:03:39 +00:00
Râu Cao
e758e258a8 Allow disabling toggles, add toggle fieldset component 2023-03-15 09:03:39 +00:00
Râu Cao
805733939c Add toggle switch component, service configs, admin profile links 2023-03-15 09:03:39 +00:00
Râu Cao
f050d010fd Refactor admin donation pages, fix errors
All checks were successful
continuous-integration/drone/push Build is passing
Not sending the right response codes for Turbo to handle.
2023-03-15 15:24:00 +07:00
Râu Cao
95fac38b53 Show email address on account settings page
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-12 11:01:22 +07:00
cb80465297 Merge pull request 'Upgrade Devise, remove custom Turbo integration' (#102) from chore/87-upgrade_devise into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #102
2023-03-09 04:43:03 +00:00
Râu Cao
c7550b4f64 Upgrade Devise, remove custom Turbo integration
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-03-09 11:34:42 +07:00
341284aa99 Merge pull request 'Refactor form input styles/layouts' (#100) from ui/form_inputs into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #100
2023-03-09 03:42:22 +00:00
Râu Cao
b34d040ce3 Refactor form input styles
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
* Fix issue where button is rendered taller in flexbox, due to default
  margin on input elements
* Refactor/improve all login and signup views
2023-03-09 10:23:16 +07:00
1142a4e2d5 Merge pull request 'Add keysend support for Lightning Addresses, specs for address/lnurlp responses' (#84) from feature/ln_address_keysend into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #84
Reviewed-by: bumi <bumi@noreply.kosmos.org>
2023-03-03 13:29:02 +00:00
Râu Cao
f2c7aa2f09 Fix typos
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-03-03 21:27:18 +08:00
cca44d7542 Merge branch 'master' into feature/ln_address_keysend
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-03-02 15:49:13 +00:00
cdad7546fb Merge pull request 'Improve design of service grid on dashboard' (#97) from feature/dashboard_layout into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #97
Reviewed-by: greg <greg@noreply.kosmos.org>
2023-03-02 15:48:27 +00:00
feb7833533 Merge branch 'master' into feature/dashboard_layout
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-03-02 15:41:51 +00:00
Râu Cao
dfb12b8f62 Fix typo
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-02 15:54:03 +08:00
Râu Cao
6c2a97e7e5 Improve design of service grid on dashboard
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-03-01 22:48:23 +08:00
c8b65de7f6 Merge pull request 'Add service attribute to LDAP user entry' (#91) from feature/ldap_services into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #91
Reviewed-by: greg <greg@noreply.kosmos.org>
2023-03-01 09:57:53 +00:00
2861254adf Merge branch 'master' into feature/ldap_services
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-03-01 09:35:53 +00:00
1d2910dadb Merge pull request 'Add pagination features, paginate admin pages' (#95) from feature/89-pagination into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #95
Reviewed-by: greg <greg@noreply.kosmos.org>
2023-03-01 09:34:58 +00:00
Râu Cao
251a170f2b Add documentation link for Pagy
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-03-01 17:14:44 +08:00
Râu Cao
cbbb4c6e47 Add pagination to admin pages
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-03-01 17:08:36 +08:00
Râu Cao
3aad27c7bd Add Pagy gem, config, styles 2023-03-01 17:08:24 +08:00
Râu Cao
7cff849d79 Add more users when seeding db 2023-03-01 17:07:13 +08:00
Râu Cao
75ffd4e2f1 Add service attribute to LDAP user entry
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-02-27 23:36:23 +08:00
b84f9109f6 Merge pull request 'Fix broken database seed' (#90) from bugfix/reserved_admin_username into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #90
Reviewed-by: raucao <raucao@noreply.kosmos.org>
2023-02-26 14:20:45 +00:00
7fd564726f Merge pull request 'Add user page to admin panel, improve other admin pages' (#88) from feature/admin_user_details into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #88
Reviewed-by: galfert <garret.alfert@gmail.com>
2023-02-26 14:16:41 +00:00
b2a1b8caf5 Remove "admin" from default reserved usernames
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Blocking admin prevents seeding the DB, which creates an admin user
2023-02-26 13:15:33 +01:00
52cc2a8151 Fix numbering in quickstart steps 2023-02-26 13:10:49 +01:00
Râu Cao
c8e405d93a Fix inline tailwind styles not being applied
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-02-26 18:41:18 +08:00
Râu Cao
5f74212603 Improve admin donation pages
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-02-26 11:33:11 +08:00
Râu Cao
1c3e893b6b Fix height of link element buttons 2023-02-26 11:32:26 +08:00
Râu Cao
eec4533fea Improve markup 2023-02-26 11:32:03 +08:00
Râu Cao
6d20ac9a1c Add lndhub info to admin user page
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-02-25 15:33:03 +08:00
Râu Cao
27dd4163f0 Add more data to admin user page 2023-02-25 15:32:50 +08:00
Râu Cao
1a55e5e895 Link users everywhere in admin panel 2023-02-25 15:32:13 +08:00
Râu Cao
8eb487600c Switch admin users index from pure LDAP to database 2023-02-25 15:31:19 +08:00
Râu Cao
678e80a25d Retrieve ldap entry from user model 2023-02-25 15:30:23 +08:00
Râu Cao
30fb9805e5 Add associations between users via invitations 2023-02-25 15:29:46 +08:00
Râu Cao
e675970f4c Add view helper for colored badges 2023-02-25 15:28:02 +08:00
Râu Cao
a0727e709f Add table class for rows with dividers 2023-02-25 15:27:28 +08:00
Râu Cao
55abbcc5ad WIP user page 2023-02-23 23:55:32 +08:00
Râu Cao
ffed398024 Add admin user details page 2023-02-23 22:09:23 +08:00
Râu Cao
1a2482434c Rename admin users controller/route
All checks were successful
continuous-integration/drone/push Build is passing
Started out as a simple helper page to list LDAP users, but turning into
proper user management now.
2023-02-23 21:53:12 +08:00
b530ad2f0f Merge pull request 'Remove ln_login from users' (#86) from chore/remove_ln_login into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #86
2023-02-23 12:16:06 +00:00
Râu Cao
3c2fe7c15d Remove ln_login from users
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Not needed anymore, removing in favor of unencrypted `ln_account`.
2023-02-23 20:13:08 +08:00
aa7044dea7 Merge pull request 'Fix deprecation warnings' (#85) from chore/fix_deprecation_warnings into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #85
2023-02-23 11:03:56 +00:00
Râu Cao
a3f0d0f2cf Fix deprecation warnings
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-02-23 19:00:03 +08:00
Râu Cao
dc63506102 Add ln node public key to test env
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-02-23 17:56:38 +08:00
Râu Cao
b87b9c2437 Prevent double render
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
2023-02-23 17:54:34 +08:00
Râu Cao
e580cc9991 Add specs for Lightning Address and lnurlpay requests
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
2023-02-23 17:46:36 +08:00
Râu Cao
68ab88c481 Add names for lnurl routes 2023-02-23 17:46:19 +08:00
Râu Cao
c7fe1bc3bc Add keysend support for Lightning Address
Allow keysend payments to user addresses. Useful for Podcasting 2.0/v4v.
2023-02-23 15:47:16 +08:00
84337c3a7d Merge pull request 'Add lndhub admin panel, quick stats for admin pages' (#80) from feature/admin_stats into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #80
Reviewed-by: bumi <bumi@noreply.kosmos.org>
2023-02-23 07:43:15 +00:00
654b90f9ee Merge pull request 'Add configurable settings, admin settings pages, reserved usernames' (#81) from feature/settings into feature/admin_stats
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Reviewed-on: #81
2023-02-23 07:42:21 +00:00
aa0ba18763 Merge pull request 'Fix password validation during password reset' (#83) from bugfix/28-password_reset into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #83
Reviewed-by: bumi <bumi@noreply.kosmos.org>
2023-02-19 14:01:25 +00:00
Râu Cao
7dae66959e Formatting
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-02-19 15:54:59 +08:00
Râu Cao
b67d6139ac Fix password validation during password reset
fixes #28
2023-02-19 15:54:55 +08:00
Râu Cao
b9259958f4 Add spec to prove issue #28
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-19 14:41:45 +08:00
Râu Cao
832d1e3bd7 Improve layout of password reset form 2023-02-19 14:41:16 +08:00
Râu Cao
f3f967f9f7 Prevent signups with reserved usernames
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
closes #12
2023-02-19 12:12:00 +08:00
Râu Cao
9407c7a94d Add username format restrictions
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-19 12:04:24 +08:00
Râu Cao
df3ec9f90a Add spec for updating reserved usernames setting
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-19 11:56:34 +08:00
Râu Cao
25a0723166 Make admin flag persist for subsequent calls in spec 2023-02-19 11:55:53 +08:00
Râu Cao
6e884b789a Show full lightning account ID/login
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
No use in hiding it, because it will be public through Lightning
Address, but can be useful for copypasta.
2023-02-18 10:08:49 +08:00
Râu Cao
346e36e160 Use success notices where appropriate
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-18 10:07:54 +08:00
Râu Cao
b7bf957dd2 Update registration settings
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-17 22:12:38 +08:00
Râu Cao
084835f06a WIP Add admin settings pages, reserved username config
All checks were successful
continuous-integration/drone/push Build is passing
Prototyping settings forms
2023-02-17 20:33:15 +08:00
Râu Cao
cd7b05e2ff Add rails-settings-cached, use for initial feature flags
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-17 17:07:42 +08:00
Râu Cao
7280a4c023 Order invitations by date on user invitations page
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-02-16 23:40:17 +08:00
Râu Cao
164400adec Merge branch 'chore/fix_ci' into feature/admin_stats
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-02-14 13:18:38 +08:00
Râu Cao
c2e0909132 Use plain hash for ENV vars
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-14 13:16:10 +08:00
Râu Cao
c44ce61e25 Remove empty tests
Some checks failed
continuous-integration/drone/push Build is failing
2023-02-14 13:06:18 +08:00
Râu Cao
e2294c4029 Add config for lndhub postgres/admin
Some checks failed
continuous-integration/drone/push Build is failing
2023-02-14 13:01:53 +08:00
Râu Cao
bdc03a7181 bundle exec rspec
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
2023-02-14 12:55:03 +08:00
Râu Cao
959449a3f4 Add default empty password
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
2023-02-13 22:10:54 +08:00
Râu Cao
b4c9b31ce7 Disable lndhub admin UI when not configured
Some checks failed
continuous-integration/drone/push Build is failing
2023-02-13 21:57:06 +08:00
Râu Cao
43f133ebd7 Add config for lndhub postgres/admin 2023-02-13 21:56:32 +08:00
Râu Cao
d9e767298b Refactor admin users page, add quick stats
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-13 16:32:28 +08:00
Râu Cao
dd482d7f2e Add LndHub db/models, and quick stats for admin views 2023-02-13 16:25:35 +08:00
Râu Cao
09d99ce9c2 Increase size of current balance 2023-02-10 11:37:27 +08:00
Râu Cao
8f9e1c3e84 Improve lnurlp message and notification
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-25 13:18:44 +08:00
4a045bf61c Merge pull request 'Various front-end improvements and bugfixes' (#78) from feature/frontend_improvements into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #78
Reviewed-by: galfert <garret.alfert@gmail.com>
Reviewed-by: bumi <bumi@noreply.kosmos.org>
2023-01-25 04:16:55 +00:00
f62e49f524 Merge pull request 'Add Webhooks and XMPP notifications for incoming sats' (#79) from feature/webhooks into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #79
Reviewed-by: bumi <bumi@noreply.kosmos.org>
2023-01-13 04:33:02 +00:00
Râu Cao
b0c787bbc7 Throw exception when user cannot be found
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-01-13 12:24:22 +08:00
Râu Cao
86dc44d096 Add empty state for wallet transactions view
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-01-12 16:21:40 +08:00
Râu Cao
a1663b9f9d Add specs for lndhub webhook
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-01-12 14:33:31 +08:00
Râu Cao
aa3c2b4fa2 Remove hardcoded user address from hook 2023-01-12 14:32:53 +08:00
Râu Cao
4c0d8283e3 Make status code explicit 2023-01-12 14:32:35 +08:00
Râu Cao
d4a3f8dadb Fix spec after renaming job
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-01-12 11:50:13 +08:00
Râu Cao
9e988e92d1 Notify user about incoming sats via XMPP
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
2023-01-12 11:44:55 +08:00
Râu Cao
4232df302b Add send_message to ejabberd service 2023-01-12 11:44:28 +08:00
Râu Cao
2c8b3cdacc Rename job 2023-01-12 11:43:30 +08:00
Râu Cao
51952ecdc2 Add migration for unencrypted ln login field
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-11 19:50:01 +08:00
Râu Cao
68e0d00f6e WIP Add Webhooks controller, allowed IP config
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-11 19:17:27 +08:00
Râu Cao
99dc36f13a Make empty donations page prettier
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-01-10 14:13:28 +08:00
Râu Cao
ee74c4847f Make invitation page prettier when it's empty 2023-01-10 14:13:27 +08:00
Râu Cao
15b63eee73 Add coming-soon note to disabled settings nav items 2023-01-10 14:13:27 +08:00
Râu Cao
c756528d32 Allow to copy invitation URLs via button 2023-01-10 14:13:27 +08:00
Râu Cao
fef29b4fc0 Add more info about project contributions 2023-01-10 14:13:27 +08:00
Râu Cao
38608e053d Add Zeus to recommended wallet apps 2023-01-10 14:13:26 +08:00
Râu Cao
5f215b8ed8 Replace vanilla JS with new clipboard code 2023-01-10 14:13:26 +08:00
Râu Cao
87aae35974 Add a clipboard controller and wire up the copy button 2023-01-10 14:13:26 +08:00
Râu Cao
6ad02e69a2 WIP Profile settings page
Show the user's user address, and provide a button for copying it to the
clipboard
2023-01-10 14:13:26 +08:00
Râu Cao
94ca0f3764 Rename settings page 2023-01-10 14:13:25 +08:00
Râu Cao
0fec37e0a9 Add inviter and time to admin invitations list 2023-01-10 14:13:25 +08:00
Râu Cao
620befd7c0 Fix devise not rendering errors as flash messages
https://github.com/heartcombo/devise/issues/5446

closes #63
2023-01-10 14:13:25 +08:00
Râu Cao
aba4930696 Set a minimum height for content with sidenav 2023-01-10 14:13:25 +08:00
Râu Cao
0492b42327 Improve button style 2023-01-10 14:13:25 +08:00
Râu Cao
445a1c80a6 Refactor settings routes and menu
Use sub controllers/routes for the sections
2023-01-10 14:13:24 +08:00
Râu Cao
cf48f76553 Fix web container start when offline 2023-01-10 14:13:24 +08:00
Râu Cao
70fa43f5d2 Use tabnav component for wallet view 2023-01-10 14:13:24 +08:00
Râu Cao
b37a0c25a4 Wording 2023-01-10 14:13:23 +08:00
Râu Cao
3197743a55 Change donations to contrbutions, add tabbed nav
Introduces components for tabbed navigation and adds a tab menu and item
for non-financial contributions to the donations/contributions page.
2023-01-10 14:13:23 +08:00
Râu Cao
3f49e4a3b8 Use more appropriate icon in sidenav 2023-01-10 14:13:23 +08:00
2e1d930e0f Merge pull request 'Docker Compose config, local 389ds/dirsrv, LDAP and user seeds' (#74) from feature/docker_compose into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #74
2022-12-27 06:26:43 +00:00
d849d28f62 Merge pull request 'Add support and migration for lndhub.go' (#77) from feature/73-lndhub-go into feature/docker_compose
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Reviewed-on: #77
2022-12-27 06:25:37 +00:00
Râu Cao
f2a22adf6b Switch legacy to lndhub.go
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Temporary fix
2022-12-23 17:42:20 +07:00
Râu Cao
e1aaa2c434 Re-authorize when token is invalid 2022-12-23 17:42:17 +07:00
Râu Cao
e62bf67262 Use v2 API for creating new lndhub accounts
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2022-12-23 12:39:57 +07:00
Râu Cao
6df3d5933c Update test env
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2022-12-22 20:11:38 +07:00
Râu Cao
a5a90c4d83 Add support and migration for lndhub.go
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
Slightly WIP
2022-12-22 20:01:14 +07:00
Râu Cao
80ef75ff42 Improve README, add quick start instructions
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2022-12-07 18:15:04 +01:00
Râu Cao
67e2e45dd8 Remove pid dir from git 2022-12-07 18:14:49 +01:00
Râu Cao
3834e5230b Comment encryption option in admin ldap users controller
Refactor to use the service later
2022-12-07 18:13:58 +01:00
Râu Cao
4cb7c0998f Add db/user seeds 2022-12-07 18:12:54 +01:00
Râu Cao
20382f7df7 Rename ldap seed task to setup 2022-12-07 18:11:57 +01:00
Râu Cao
add94eee8d Don't start phpldapadmin by default 2022-12-07 18:11:23 +01:00
Râu Cao
067dc3b63d Remove obsolete method 2022-12-07 18:11:03 +01:00
Râu Cao
1a470cf1c8 Add flag for creating pre-confirmed users 2022-12-07 18:09:44 +01:00
Râu Cao
f85b7f4f62 Define patch version for Ruby base image
No need to re-download new images for every patch version
2022-12-07 18:07:53 +01:00
Râu Cao
8635413002 Delete admin role manually on reset
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2022-12-07 15:20:34 +01:00
Râu Cao
a3da956b48 Add missing ACI and role to LDAP seeds
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2022-12-07 14:27:51 +01:00
Râu Cao
3c40dc98ca Add note about resetting LDAP server
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2022-12-06 10:28:34 +01:00
28b31e63f9 Merge pull request 'Update Docker image in CI' (#75) from chore/ci_image_upgrade into feature/docker_compose
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Reviewed-on: #75
2022-12-06 09:23:05 +00:00
Râu Cao
efafd38f68 Update Docker image in CI
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
We need a newer node.js version.
2022-12-06 10:19:47 +01:00
Râu Cao
537e1a4774 Update database schema (from Rails upgrade)
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
2022-12-05 13:36:49 +01:00
Râu Cao
c3b9ff8b4a Add LDAP service and seed task 2022-12-05 13:36:33 +01:00
Râu Cao
93d56f79d5 Add config and documentation for running dirsrv with Docker 2022-12-05 13:35:30 +01:00
Râu Cao
1a30345f46 Add byebug for debugging in development 2022-12-05 13:20:47 +01:00
Râu Cao
778babcc05 Add Docker Compose config and 389ds service
Some checks failed
continuous-integration/drone/push Build is failing
refs #2
2022-12-02 19:21:13 +01:00
Râu Cao
fa3b53d3b3 Add Dockerfile for development 2022-12-02 19:19:02 +01:00
Râu Cao
0ca85656b7 Update dependencies 2022-12-02 19:16:56 +01:00
Râu Cao
f7183f68d5 Decrease mininum sats for Lighting invoices
All checks were successful
continuous-integration/drone/push Build is passing
2022-09-16 11:20:29 +02:00
87027b514b Merge pull request 'Update gems' (#72) from chore/update_gems into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #72
2022-07-27 13:47:33 +00:00
Râu Cao
16ad621365 Update gems
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
In particular Rails due to security updates:

https://rubyonrails.org/2022/7/12/Rails-Versions-7-0-3-1-6-1-6-1-6-0-5-1-and-5-2-8-1-have-been-released
2022-07-27 15:22:24 +02:00
33e87d6472 Merge pull request 'Add BTCPay service, Kredits API' (#71) from feature/community_funds_balance into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #71
Reviewed-by: bumi <bumi@noreply.kosmos.org>
2022-06-12 05:15:05 +00:00
03dc6c7a9c Log unexpected kredits API errors
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2022-05-24 13:42:00 +02:00
897b5bf4ea Specify whole API base URL in config
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2022-05-23 22:49:39 +02:00
caea2d0121 Add kredits API with wallet balance endpoint
All checks were successful
continuous-integration/drone/push Build is passing
2022-05-23 22:47:08 +02:00
e1ff5c479e Initial BTCPay integration 2022-05-23 21:35:03 +02:00
9b3386de30 Update credentials 2022-05-23 18:49:37 +02:00
f2287c1186 Remove separate development credentials files 2022-05-23 18:49:22 +02:00
b29197cf4e Merge pull request 'Various UI improvements' (#70) from feature/ui_improvements into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #70
2022-04-28 13:05:10 +00:00
5c48055ac8 Use feather icon for wallet on dashboard
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
fixes #51
2022-04-28 15:01:20 +02:00
5ead3476b7 Normalize overall (font) size
The entire UI is a bit too large. This normalizes the font size and
dimensions, so it doesn't look zoomed in on most screens.
2022-04-28 14:56:03 +02:00
fbf163740a Merge pull request 'Replace the LDAP production config for the new server' (#69) from chore/new_ldap_server into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #69
2022-04-28 10:11:01 +00:00
Greg Karékinian
1fc1457e97 Replace the LDAP production config for the new server
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Refs kosmos/chef#227
2022-04-28 11:54:14 +02:00
1f57bbd9c2 Merge pull request 'Add admin task to list LndHub balances' (#68) from feature/list_lndhub_balances into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #68
2022-04-18 08:41:40 +00:00
2a2793ae44 Print sum of user balances
All checks were successful
continuous-integration/drone/pr Build is passing
2022-04-12 16:05:46 +02:00
8773bf5f9e Slow down LndHub auth requests in task 2022-04-12 15:42:44 +02:00
d9970c126a List balances of LndHub accounts 2022-04-12 15:36:45 +02:00
4e0d4bf86d 0.4.0
All checks were successful
continuous-integration/drone/push Build is passing
2022-03-17 14:59:07 -06:00
333bcbfe7e Remove Sass dependency
All checks were successful
continuous-integration/drone/push Build is passing
2022-03-17 13:30:10 -06:00
875af6d14c Merge pull request 'Add transaction history view to wallet' (#66) from feature/wallet_history into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #66
2022-03-17 19:28:58 +00:00
8f87a03060 Merge pull request 'Finish Tailwind migration' (#67) from chore/finish_tailwind_migration into feature/wallet_history
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Reviewed-on: #67
2022-03-17 19:27:52 +00:00
7838fe5f34 Remove legacy CSS build from task
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2022-03-17 13:26:36 -06:00
512798d122 Port last remaining styles from legacy to Tailwind
Some checks failed
continuous-integration/drone/pr Build is failing
continuous-integration/drone/push Build is failing
2022-03-17 13:24:13 -06:00
384c28aaaa Build PRs for all branches
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2022-03-17 13:06:33 -06:00
8e5d6dabdc Port most remaining legacy styles to Tailwind
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2022-03-11 10:15:09 -06:00
ade9261c2c Remove obsolete CSS 2022-03-11 09:52:11 -06:00
bd2a161306 Add tab menu to wallet pages
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2022-03-02 19:18:28 -06:00
78c243c985 Add wallet transactions
All checks were successful
continuous-integration/drone/push Build is passing
2022-03-02 18:43:22 -06:00
cf62bfc5c2 WIP Add wallet transactions route, view
All checks were successful
continuous-integration/drone/push Build is passing
Adds a new component for the wallet summary as well, and makes the
component tests work with RSpec.
2022-03-02 15:31:39 -06:00
10f179a095 Port shared CSS for tables to Tailwind 2022-03-02 15:30:50 -06:00
f7d0a0ba85 0.3.0
Some checks failed
continuous-integration/drone/push Build is failing
2022-03-02 10:41:54 -06:00
83e4dfa18f Merge pull request 'Allow comments for LNURL-PAY invoices' (#65) from feature/lnurlp_memos into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #65
2022-03-02 14:13:40 +00:00
4c70600d1f Re-add description_hash
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Necessary for lnurlpay-enabled wallets
2022-03-01 13:53:22 -06:00
9903683536 Remove desc hash, always add memo to invoices
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2022-03-01 13:26:44 -06:00
4c51b9c966 Allow comments for LNURL-PAY invoices
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Allows senders to add a short message to payments, which will be stored
as invoice memo by LND/LndHub.
2022-03-01 11:20:23 -06:00
6790e8383d Merge pull request 'Redesign layout and navigation' (#64) from feature/new_layout into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #64
2022-02-26 15:45:12 +00:00
ed886d8182 Introduce sidebar nav components, settings nav
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2022-02-24 18:56:07 -06:00
ca940ec35d Consolidate some styles
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2022-02-24 17:24:59 -06:00
5751c0338a Nicer buttons on small screens
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2022-02-24 13:59:51 -06:00
b9ec363f36 Remove caveat from README 2022-02-24 13:59:15 -06:00
417768a30c Fix specs, markup
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2022-02-23 18:27:33 -06:00
9824dcd2c6 Remove unused specs
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is failing
2022-02-23 18:17:43 -06:00
5a784b5fa6 Improve devise views
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is failing
2022-02-23 18:16:14 -06:00
f36f6866a7 Port signup to new layout
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is failing
2022-02-23 18:07:54 -06:00
1fecfe57de Fix status views 2022-02-23 17:50:16 -06:00
3165714957 Implement proper mobile navigation
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is failing
2022-02-23 14:16:51 -06:00
4ccf43cf4a Layout classes 2022-02-23 12:13:14 -06:00
c0e79918ea Fix confirm dialog missing
All checks were successful
continuous-integration/drone/push Build is passing
2022-02-21 11:20:58 -06:00
2b00eebb73 Fix delete link, remove obsolete notice
All checks were successful
continuous-integration/drone/push Build is passing
2022-02-21 11:19:07 -06:00
86cdb1202b Port check-email screen to new layout 2022-02-21 11:09:57 -06:00
6a469d6a75 Allow empty values for fiat conversion 2022-02-21 11:09:44 -06:00
7d66b75216 Improve notifications, fix styles not being added
All checks were successful
continuous-integration/drone/push Build is passing
Based on https://petr.codes/blog/rails/modern-rails-flash-messages/part-3/
2022-02-21 11:03:43 -06:00
8102fa1230 WIP Add notification component for flash messages
All checks were successful
continuous-integration/drone/push Build is passing
2022-02-20 17:22:49 -06:00
835152c656 Introduce ViewComponent
All checks were successful
continuous-integration/drone/push Build is passing
https://viewcomponent.org
2022-02-20 16:53:11 -06:00
7c5bd9aa34 Improve focused field style
All checks were successful
continuous-integration/drone/push Build is passing
2022-02-20 12:54:16 -06:00
b329b557c4 Add compact layout for content, port sign-in screens
All checks were successful
continuous-integration/drone/push Build is passing
2022-02-20 12:48:11 -06:00
2e301c3019 Port admin to new layout
All checks were successful
continuous-integration/drone/push Build is passing
2022-02-20 11:22:06 -06:00
4f2b35ccb9 WIP New app layout
All checks were successful
continuous-integration/drone/push Build is passing
2022-02-19 22:46:12 -06:00
a2889705ed Merge pull request 'Fix sign out link' (#62) from bugfix/signout into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #62
2022-02-19 18:16:00 +00:00
7cb0111449 Fix sign out link
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
The correct HTML attribute to send a DELETE request would be
`data-turbo-method`, but then it still fails with JS turned off, which
is unnecessary.

fixes #61
2022-02-19 12:12:32 -06:00
773ea24c5d Merge pull request 'Switch from Webpacker to cssbundling-rails, upgrade Tailwind CSS to version 3' (#59) from dev/cssbundling into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #59
Reviewed-by: bumi <bumi@noreply.kosmos.org>
2022-02-17 14:45:18 +00:00
cd3e4161b8 Update dev command in README
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2022-02-16 10:46:04 -06:00
5a658ce580 Update RSpec syntax/usage
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Fixes a deprecation warning
2022-02-16 10:14:32 -06:00
6e9b38f04b Fix deprecation warning from Rails
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2022-02-16 09:41:07 -06:00
a71a9dfad0 Remove unused helper specs
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2022-02-16 09:38:40 -06:00
1c4e444c0b Adjust bundle options in CI
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2022-02-16 09:25:47 -06:00
565a3c3276 Fix broken name
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is failing
2022-02-12 15:34:18 -06:00
9fdbf27a60 Use rake tasks in CI
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is failing
2022-02-12 15:29:04 -06:00
1a9b47ceee Losing the battle
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is failing
2022-02-12 15:22:57 -06:00
908809bc48 Remove bundler version requirement
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is failing
2022-02-12 15:11:34 -06:00
9636671d57 Use rspec binstub in CI
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is failing
2022-02-12 15:10:23 -06:00
51cddd94f5 Add rspec binstub 2022-02-12 15:09:56 -06:00
123e7aa2a1 Update Gemfile 2022-02-12 15:09:41 -06:00
3596955642 Don't use deprecated bundler flags 2022-02-12 15:09:19 -06:00
562b16cf89 Update Rails CI Docker image
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is failing
2022-02-12 15:02:20 -06:00
830c634f88 Explicitly install dev and test gems
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is failing
2022-02-12 14:55:30 -06:00
2a793e9201 Define RAILS_ENV in CI
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is failing
2022-02-12 14:53:23 -06:00
e571ed9429 Use vanilla Yarn to build CSS in CI
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is failing
2022-02-12 14:43:51 -06:00
a67f3e466b Remove bootsnap
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is failing
2022-02-12 14:41:47 -06:00
ff3013f917 Remove all remains of Webpack
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is failing
2022-02-12 14:30:31 -06:00
0fa6c1a211 Don't pin bootsnap version
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is failing
2022-02-12 14:26:14 -06:00
30b2646b85 Fix rake command
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is failing
2022-02-12 14:22:53 -06:00
f8b86b0a22 Remove obsolete gems
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is failing
2022-02-12 14:21:21 -06:00
b71a2fa643 Merge pull request 'Upgrade Rails to 7.0.2, use native JS bundling' (#60) from dev/upgrade_rails into dev/cssbundling
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is failing
Reviewed-on: #60
2022-02-12 20:13:42 +00:00
eda1f3999f Update validation message in spec
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
They seem to have shortened the default message.
2022-02-12 14:10:04 -06:00
c06e58a0fb Use new lockbox method
The old one conflicts with Rails' own new ActiveRecord encryption
feature.
2022-02-12 14:04:41 -06:00
c33637003e Upgrade to Rails 7, new JS build setup 2022-02-12 13:55:56 -06:00
836bd0a977 Build CSS bundles in CI
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is failing
2022-02-12 13:55:30 -06:00
8578fbdad9 Build legacy CSS via cssbundling as well
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is failing
Add vanilla Sass builds that are also handled by cssbundling-rails.
2022-02-12 13:52:45 -06:00
878eac083c Move legacy (S)CSS files to legacy folder
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is failing
2022-02-12 12:43:37 -06:00
05da7f5dac Bump package version
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is failing
2022-02-12 10:01:19 -06:00
87e3b1a76c Sign Drone config 2022-02-12 09:34:36 -06:00
32f02cc18a Switch from Webpacker to cssbundling-rails, upgrade Tailwind 2022-02-11 17:23:31 -06:00
1b17cfb396 Fix typo
All checks were successful
continuous-integration/drone/push Build is passing
2022-02-03 11:32:41 -06:00
e5aa5a665c Merge pull request 'Fix LNURL pay amount validation' (#58) from bugfix/fix-max-receivable-amount into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #58
2022-02-03 17:13:20 +00:00
d37b68a6e5 Fix LNURL pay amount validation
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
We allow receiving of more than 100 sats and less than 1M sats
2022-02-03 17:32:18 +01:00
56936916ff Move SVG images to public folder
All checks were successful
continuous-integration/drone/push Build is passing
Wasn't working in production
2022-01-12 19:37:12 -06:00
c93a460cff Bump style version
All checks were successful
continuous-integration/drone/push Build is passing
Triggers rebuild
2022-01-12 18:52:32 -06:00
f5ceda35c1 Merge pull request 'Add more content/help to wallet page' (#57) from feature/wallet_page_content into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #57
2022-01-13 00:48:22 +00:00
eb0439d6dc Improve Blue Wallet instructions
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2022-01-12 18:46:14 -06:00
c3dde3506e Add more content/help to wallet page
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
* Lighting Address info
* Improve explanation for wallet apps, add Alby
2022-01-10 13:37:04 -06:00
f22ffe373c Merge pull request 'Fix exception during signup' (#56) from bugfix/signup_lndhub into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #56
2022-01-10 15:31:10 +00:00
bc20e89617 Fix exception during signup
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2022-01-10 09:28:12 -06:00
0f0f296a5e Merge pull request 'Add button for copying lndhub setup code' (#55) from feature/37-copy_setup_code into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #55
2021-12-16 14:23:13 +00:00
78aea5d608 Use Tailwind classes to hide/show elements
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2021-12-16 15:18:37 +01:00
f1d3e3d8ec Add button for copying lndhub setup code
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
closes #37
2021-12-15 14:54:44 +01:00
2706c76890 Merge pull request 'Improve admin LDAP user index' (#53) from feature/improve_admin_ldap_page into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #53
2021-11-30 14:38:05 +00:00
17f5eb56cd Merge pull request 'Show sats instead of BTC on donation page, refactor CSS' (#54) from feature/45-sats_everywhere into master
Some checks are pending
continuous-integration/drone/push Build is running
Reviewed-on: #54
2021-11-30 14:37:45 +00:00
aa6b677b13 Merge pull request 'Improve task for generating invitations' (#52) from feature/improve_invitation_generation into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #52
2021-11-28 20:44:06 +00:00
9abdab2274 Show sats instead of BTC on donation page, refactor CSS
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
* Show sats instead of BTC on donation page
* Use number delimiters on both donation page and wallet page
* Refactor donation page CSS into Tailwind directives
2021-11-28 11:53:20 -06:00
dd49d1208f Remove feature list from README
All checks were successful
continuous-integration/drone/push Build is passing
Not overly useful or impressive IMO.
2021-11-28 11:16:49 -06:00
db9118cb7c Improve admin LDAP user index
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
* Show which domain the current list is for
* Render text links as such
2021-11-28 11:11:41 -06:00
89913ba60b Improve task for generating invitations
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Turn the argument into the target number of unused invitations for each
user, thus not generating more invitations for users who already have a
sufficient amount of unused ones.
2021-11-28 10:40:09 -06:00
8cf631fd94 Add preconfigured lockbox credentials for development
All checks were successful
continuous-integration/drone/push Build is passing
2021-11-26 13:05:26 -06:00
d0b359039b Merge pull request 'Wrap global JS into IIFE' (#50) from bugfix/41-turbolinks into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #50
2021-11-26 19:04:34 +00:00
84cf523049 Wrap global JS into IIFE
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
fixes #41
2021-11-26 13:01:39 -06:00
a7390ba00b Merge pull request 'Fixes/improvements for lnurl-pay' (#49) from feature/lnurlp_improvements into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #49
2021-11-26 17:37:37 +00:00
67d148d117 Lower the minimum receivable via lnurlp
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2021-11-26 11:34:51 -06:00
83ad6f4eef Update README
All checks were successful
continuous-integration/drone/push Build is passing
2021-11-25 19:24:56 -06:00
2e31268698 Change description and success message for lnurlp
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
closes #46
2021-11-25 19:14:43 -06:00
f3b22c02ef Set correct min/max amounts for lnurlp
fixes #47
2021-11-25 19:14:17 -06:00
dbe65b4b5a Merge pull request 'Add lndhub and lockbox configs for test environment' (#48) from bugfix/lndhub_specs into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #48
2021-11-26 00:55:18 +00:00
2871fc0f53 Add lockbox credentials for test env
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2021-11-25 18:51:40 -06:00
968689a512 Add lndhub config to test environment
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is failing
2021-11-25 18:38:54 -06:00
ab29f618f4 Update README
Some checks failed
continuous-integration/drone/push Build is failing
2021-11-24 11:11:36 -06:00
94975a1b30 Merge pull request 'Add Tailwind info to README' (#44) from bugfix/35-tailwind-2 into master
Some checks failed
continuous-integration/drone/push Build is failing
Reviewed-on: #44
2021-11-24 17:10:26 +00:00
cd8880d9dc Add Tailwind info to README
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
2021-11-24 11:03:42 -06:00
f59182b9c1 Second try, triggering asset compilation
Some checks failed
continuous-integration/drone/push Build is failing
2021-11-24 10:48:29 -06:00
941cb4a571 Minor CSS tweak
Some checks failed
continuous-integration/drone/push Build is failing
2021-11-24 10:45:40 -06:00
f534898d8b Try triggering asset compilation
Some checks failed
continuous-integration/drone/push Build is failing
2021-11-24 10:42:40 -06:00
18c7c54403 Merge pull request 'Various UI improvements' (#43) from ui/misc into master
Some checks failed
continuous-integration/drone/push Build is failing
Reviewed-on: #43
2021-11-24 02:41:55 +00:00
12a9d4674b Fix a couple of oversights
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
2021-11-23 20:40:42 -06:00
1af8e068c5 Add the wallet to the dashboard as a service
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
2021-11-23 20:09:30 -06:00
669b163814 Make the wallet balance look a bit nicer 2021-11-23 20:08:54 -06:00
46c7affd1f Add explanatory intro to invitations page 2021-11-23 20:08:33 -06:00
7ab107b689 Hide headings
The main nav entry above is enough context.
2021-11-23 20:07:57 -06:00
5aee1a4100 Merge pull request 'Fix main nav on small screens' (#42) from bugfix/38-navbar into master
Some checks failed
continuous-integration/drone/push Build is failing
Reviewed-on: #42
2021-11-23 22:02:36 +00:00
1578fb9976 Fix main nav on small screens
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
closes #38
2021-11-23 16:00:32 -06:00
8e64a7cf78 Merge pull request 'Fix invoice amount for lnurlp payments' (#40) from bugfix/lnurlp_amounts into master
Some checks failed
continuous-integration/drone/push Build is failing
Reviewed-on: #40
2021-11-23 21:29:33 +00:00
8b5bd66598 Fix invoice amount for lnurlp payments
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
Incoming amount is msats, but we create invoices with sats.
2021-11-23 15:28:16 -06:00
ac8552362c Merge pull request 'Adjust tailwind purge config' (#39) from bugfix/35-tailwind into master
Some checks failed
continuous-integration/drone/push Build is failing
Reviewed-on: #39
2021-11-23 21:27:22 +00:00
99c86c42c5 Adjust tailwind purge config
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
2021-11-23 15:15:10 -06:00
d0267cb760 Update README
Some checks failed
continuous-integration/drone/push Build is failing
2021-11-22 17:05:46 -06:00
25ddab9241 Merge pull request 'Add LndHub wallets' (#33) from feature/lndhub into master
Some checks failed
continuous-integration/drone/push Build is failing
Reviewed-on: #33
2021-11-22 23:04:19 +00:00
bf76ac55ee Do not allow comments for lnurlp senders
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
2021-11-22 17:03:18 -06:00
40e5c3609e Remove obsolete files
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
2021-11-22 16:29:23 -06:00
1078c034ad Remove obsolete comment
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
2021-11-22 16:26:05 -06:00
bfa38ad7b2 Adjust spec for new development config
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
2021-11-22 16:24:42 -06:00
4f20cd0d0a Add Rake task for generating wallets
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
2021-11-22 16:22:53 -06:00
e2ee33a1da Configure LndHub for production
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
2021-11-22 16:19:16 -06:00
8662a4c8c1 Don't overwrite existing lndhub wallet credentials
Some checks failed
continuous-integration/drone/pr Build is failing
continuous-integration/drone/push Build is failing
2021-11-22 15:51:30 -06:00
dbc811b840 Add LndHub service, lnurl-pay endpoints
Some checks failed
continuous-integration/drone/pr Build is failing
continuous-integration/drone/push Build is failing
Enables the lnurl-pay payment workflow
2021-11-22 15:41:05 -06:00
884070a3cb Show available balance on wallet page
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
2021-11-21 16:47:55 -06:00
3c350155de Formatting
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
2021-11-21 15:34:24 -06:00
21c6ebc137 Fix small issue with turbolinks
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
The JS was run again, and failed to assign variables using `const` then.
2021-11-21 13:27:55 -06:00
0a1052fcb7 Add wallet page
Some checks failed
continuous-integration/drone/pr Build is failing
continuous-integration/drone/push Build is failing
With setup code to connect Blue Wallet to Kosmos account wallets
2021-11-20 16:13:43 -06:00
f94227f9f3 Create LndHub accounts 2021-11-19 20:10:36 -06:00
088961dfec Merge pull request 'Switch to shared Kosmos font(s)' (#30) from feature/webfonts_open-sans into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #30
2021-02-25 17:11:39 +00:00
31cf353d3a Load remote fonts before other stylesheets
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
They won't apply when loaded afterwards.
2021-02-25 18:04:27 +01:00
4eb40abc9c Import webfont from shared URL
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2021-02-19 15:45:22 +01:00
682c78c7c3 Move headline styles to tailwind base
All checks were successful
continuous-integration/drone/push Build is passing
2021-02-19 15:11:53 +01:00
f9726ad9be Use Open Sans as default font for everything 2021-02-19 15:02:07 +01:00
89188f5081 Don't purge CSS in base and component layers
All checks were successful
continuous-integration/drone/push Build is passing
The production build was purging input[type=text] styles, because it
couldn't find it in the Rails templates. Change config, so it only
purges utility classes.
2021-02-10 16:37:34 +01:00
6a6ff84ff2 Merge pull request 'Add Tailwind CSS, migrate most of the styles' (#27) from feature/tailwind-css into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #27
2021-02-10 14:29:06 +00:00
b6949acc96 Style forms, migrate more styles to Tailwind
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2021-02-09 20:32:10 +01:00
814633034f WIP Add Tailwind CSS
All checks were successful
continuous-integration/drone/push Build is passing
2021-02-09 02:05:31 +01:00
260dedb6cf Merge pull request 'Set up async workers/jobs via Sidekiq' (#26) from feature/sidekiq into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #26
2021-02-03 18:12:48 +00:00
656c887811 Add missing hook to spec
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2021-02-03 19:11:43 +01:00
7e9af716ac Make them colors pop
All checks were successful
continuous-integration/drone/push Build is passing
2021-02-03 13:37:44 +01:00
58cc6811f9 Move XMPP contacts exchange to background job
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2021-02-03 13:16:47 +01:00
8ad85636d9 Create LDAP users asynchronously
All checks were successful
continuous-integration/drone/push Build is passing
2021-02-02 21:16:24 +01:00
35e2c8cd30 Add Sidekiq, configure admin access to Web UI
All checks were successful
continuous-integration/drone/push Build is passing
2021-02-02 11:44:17 +01:00
4526c941b8 Merge pull request 'Add invitations page to admin panel' (#24) from feature/admin_invitations into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #24
2021-02-01 22:53:31 +00:00
4f5ebd5330 Merge pull request 'Add cosmic background to header' (#25) from ui/kosmic_sky into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #25
2021-02-01 22:53:15 +00:00
d7e4c6f3ae Add cosmic background to header
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Going back to space, where we belong.
2021-02-01 23:10:54 +01:00
14caefe2d1 Replace yellow menu highlight with blue color 2021-02-01 22:49:42 +01:00
0110f27ada Add invitation stats
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Show some stats about unused invitations and active inviters
2021-02-01 22:35:30 +01:00
dc7cf107c2 New admin page for invitations 2021-02-01 21:53:18 +01:00
4fbfaadb44 Merge pull request 'Various UI improvements' (#23) from ux/various_design_changes into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #23
2021-02-01 18:33:06 +00:00
a01cb9ae21 Adjust site header in admin, signup layouts
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2021-02-01 18:58:34 +01:00
698e4381c2 Improve table styles
All checks were successful
continuous-integration/drone/push Build is passing
* Nicer table headers
* Hide invitation IDs on small screens
2021-02-01 18:53:48 +01:00
8997349186 Move password change to new Security tab
All checks were successful
continuous-integration/drone/push Build is passing
2021-02-01 18:39:51 +01:00
92bfc33bf0 Remove bottom border from last section on page 2021-02-01 18:24:01 +01:00
c6eb21faad Change site name to "Account", add comet icon
All checks were successful
continuous-integration/drone/push Build is passing
... and remove the "beta" tag.
2021-02-01 18:17:26 +01:00
2d9bc90b16 Merge pull request 'Use new .local domain for Postgres in production' (#22) from chore/postgres_hostname into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #22
2021-01-23 14:04:45 +00:00
a0c579e319 Use new .local domain for Postgres in production
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2021-01-23 15:03:16 +01:00
f289ee9365 Switch menu items
All checks were successful
continuous-integration/drone/push Build is passing
2020-12-29 11:09:04 +01:00
46a7345ce9 Merge pull request 'Add main navigation bar' (#20) from feature/main_nav into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #20
2020-12-29 10:04:42 +00:00
e12d02a988 Fix spec
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Content changed
2020-12-29 11:02:24 +01:00
5e8618f25a Merge pull request 'Add admin layout with admin navigation' (#21) from feature/admin_layout into feature/main_nav
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is failing
Reviewed-on: #21
2020-12-29 09:58:57 +00:00
2bdf08a523 Add admin layout with admin navigation
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
And remove the hacky link list from the dashboard.
2020-12-28 09:32:04 +01:00
9ddd36c414 Add missing section markup
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2020-12-27 14:21:16 +01:00
9372ea7343 Add small-screen layout for main navigation 2020-12-27 14:14:53 +01:00
c62ce00184 Add main navigation bar
Make donations and invitations accessible to everyone
2020-12-27 14:03:40 +01:00
4d8cd740ba Argh
All checks were successful
continuous-integration/drone/push Build is passing
2020-12-22 17:15:46 +01:00
9858572a2f Remove useless bundler version requirement
All checks were successful
continuous-integration/drone/push Build is passing
2020-12-22 17:03:14 +01:00
51edf55ae9 Use zerotier for connecting to postgres
All checks were successful
continuous-integration/drone/push Build is passing
2020-12-22 12:24:18 +01:00
75485ce8e9 Merge pull request 'Update postgres master host' (#19) from chore/update_postgres_host into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #19
2020-12-22 10:42:51 +00:00
fcbfcc4007 Update postgres master host
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2020-12-22 11:41:40 +01:00
cdcb7b3aef Update README
All checks were successful
continuous-integration/drone/push Build is passing
2020-12-21 15:49:58 +01:00
bcf5172956 Merge pull request 'Add basic donation records' (#18) from feature/donation_records into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #18
2020-12-21 14:46:50 +00:00
26c6c5a3b2 Nullify donation owners when related record destroyed
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2020-12-21 13:59:46 +01:00
4a65573934 Format numbers on admin donations page
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
And fix the wrong unit display in the user donations list.
2020-12-19 14:59:16 +01:00
5e2d5c3b28 Add paid_at date to donations
All checks were successful
continuous-integration/drone/push Build is passing
2020-12-19 13:28:47 +01:00
2f70bae523 Format and style user donations 2020-12-19 13:16:04 +01:00
40f3e8327a Basic donation records
Adds donation model/table and basic manual management in the admin
panel, as well as basic listing of users' own donations.
2020-12-17 21:56:51 +01:00
f3d6e29e4e Remove time from used invitations list
Date is enough.
2020-12-17 17:02:30 +01:00
8903ae2624 Merge pull request 'Fix XMPP API POST request' (#17) from bugfix/faraday_post into master
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
Reviewed-on: #17
2020-12-13 13:17:57 +00:00
26e9073674 Fix XMPP API POST request
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
Faraday does not turn hashes into JSON by itself apparently.
2020-12-13 14:07:25 +01:00
73a89c2601 Merge pull request 'Add missing port number to ejabberd API base URL' (#16) from bugfix/ejabberd_http_port into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #16
2020-12-13 12:57:34 +00:00
7d4dee17b7 Add missing port number to ejabberd API base URL
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2020-12-13 13:54:33 +01:00
602ca6ee94 Merge pull request 'Exchange XMPP contacts when invitee signs up' (#13) from feature/automatic_xmpp_roster into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #13
2020-12-09 20:52:14 +00:00
69fc1ca57e Add production dotenv config
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2020-12-08 20:34:13 +01:00
ee72a32c7e Exchange XMPP contacts when invitee signs up
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2020-12-08 19:16:08 +01:00
8a0d89ef60 Add webmock gem 2020-12-08 18:16:41 +01:00
54af949c7d Add faraday for HTTP requests 2020-12-08 18:16:41 +01:00
6dac732a7f Move invitation invalidation to service 2020-12-08 17:52:53 +01:00
e8c1a6066a Move user db creation to service 2020-12-08 17:39:54 +01:00
44fadb12d6 Merge pull request 'Update link to Chat service' (#11) from chore/update_service_link into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #11
2020-12-04 15:18:49 +00:00
533452469b Update link to Chat service
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
The wiki page has been moved and improved for new users.
2020-12-04 16:15:17 +01:00
efe168b205 Merge pull request 'Sign up for new account via invitation' (#9) from feature/signup_from_invite into master
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
Reviewed-on: #9
2020-12-04 12:30:28 +00:00
5b6d6bbd00 Explain ApplicationService
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2020-12-04 13:29:07 +01:00
458b585cdb Check off invitation signup feature in README
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2020-12-03 15:14:13 +01:00
f651289410 Add mailer host config for test
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
So Devise can build URLs in confirmation emails
2020-12-03 14:59:21 +01:00
7ca91cf882 Don't run caching steps on CI when not master or PR
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is failing
2020-12-03 14:56:11 +01:00
022094ce51 Add feature spec for whole signup process
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is failing
2020-12-03 14:50:02 +01:00
2a2b0a90dc Validate email address properly 2020-12-03 14:49:37 +01:00
e44535daee Don't use deprecated method 2020-12-03 14:49:16 +01:00
c8ccb418b2 Add indexes for invitations table 2020-12-03 14:49:02 +01:00
a792d66c90 Show unused invitations list 2020-12-03 14:48:43 +01:00
f7e48ad3a6 Accept non-existing terms
Legal how does it work
2020-12-03 14:47:57 +01:00
8a7d809b92 Add scopes for invitations 2020-12-03 14:04:58 +01:00
b8e75c7c4a Re-order services on dashboard
All checks were successful
continuous-integration/drone/push Build is passing
Docs and forums are more important for most users than Gitea and Drone.
2020-12-03 13:50:07 +01:00
7a58babd8e Remove obsolete argument
All checks were successful
continuous-integration/drone/push Build is passing
2020-12-03 13:48:23 +01:00
ba31ed559a Improve wording
All checks were successful
continuous-integration/drone/push Build is passing
2020-12-03 00:53:43 +01:00
9cebfd3f58 Signup steps with validation 2020-12-03 00:53:25 +01:00
7aadb5cb51 Require valid invitation to start sign-up process
All checks were successful
continuous-integration/drone/push Build is passing
2020-12-02 19:20:01 +01:00
69b99711e5 Remove fixtures, configure factory generation
All checks were successful
continuous-integration/drone/push Build is passing
2020-12-02 15:40:41 +01:00
e5fe843814 Add task for generating invitations
All checks were successful
continuous-integration/drone/push Build is passing
2020-12-02 15:23:18 +01:00
d7fbda0855 Add basic invitations 2020-12-02 15:22:58 +01:00
18df8fe449 Add account creation service 2020-11-29 17:31:08 +01:00
fd2ebc4ad3 Merge pull request 'Cache dependencies on CI' (#6) from chore/cache_bundle_on_ci into master
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
Reviewed-on: #6
2020-11-26 15:44:19 +00:00
c86480e72b Cache dependencies on CI
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
https://florian-latifi.at/2018/02/21/using-drone-to-build-and-deploy-a-jekyll-site/
https://git.florian-latifi.at/flortsch/jekyll-blog/src/branch/master/.drone.yml
2020-11-21 23:17:12 +01:00
5933c387b6 Set correct email address for devise
All checks were successful
continuous-integration/drone/push Build is passing
2020-11-21 17:17:33 +01:00
e855e3cf61 Merge pull request 'Gracefully fail config build when master secret not available' (#5) from bugfix/config_without_master_key into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #5
2020-11-21 15:28:55 +00:00
91c3f8da2d Gracefully fail config build when master secret not available
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
When the credentials are not accessible, e.g. on CI, parsing the
database config fails otherwise.
2020-11-21 16:22:11 +01:00
8bd69b2adb Add missing postgres gem
Some checks failed
continuous-integration/drone/push Build is failing
Needed in production
2020-11-21 14:12:09 +01:00
8493dfcf9b Add missing string quotes
Some checks failed
continuous-integration/drone/push Build is failing
2020-11-21 14:07:01 +01:00
6550a8b4f8 Merge pull request 'Add production config and credentials' (#4) from chore/production_prep into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #4
2020-11-21 13:03:16 +00:00
fa8650b43a Improve email config
Some checks failed
continuous-integration/drone/pr Build is failing
continuous-integration/drone/push Build is passing
Add specific auth options, specify sender address
2020-11-20 22:47:35 +01:00
8a938831e9 Add production config and credentials
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is failing
2020-11-20 22:43:47 +01:00
151bd58cb4 Speed up bundle-install on CI
All checks were successful
continuous-integration/drone/push Build is passing
2020-11-19 19:04:24 +01:00
98b5af54ea Add Drone CI to service grid
All checks were successful
continuous-integration/drone/push Build is passing
2020-11-19 17:28:44 +01:00
61b722e868 Merge pull request 'Configure CI builds' (#3) from dev/configure_drone_ci into master
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #3
2020-11-19 15:40:46 +00:00
0eab4f03ac Remove Ruby version lock from Gemfile
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2020-11-19 14:29:16 +01:00
c96a84d1a1 Add initial Drone CI config 2020-11-19 14:29:07 +01:00
86cd5824e6 Document current and planned features
Only rough priorities for planned ones, of course. Not at all complete.
2020-11-18 16:03:21 +01:00
d420ef9eac Link to license info page in README 2020-11-18 15:38:36 +01:00
a7a3974ef3 Add AGPL license 2020-11-18 15:32:27 +01:00
cd59215b69 Update README 2020-11-18 15:28:17 +01:00
0b125cf323 Introduce media queries and small screen adjustments 2020-11-18 15:13:45 +01:00
653 changed files with 13423 additions and 8416 deletions

59
.drone.yml Normal file
View File

@@ -0,0 +1,59 @@
---
kind: pipeline
type: docker
name: CI build
steps:
- name: restore-cache
image: drillster/drone-volume-cache
volumes:
- name: cache
path: /cache
settings:
restore: true
mount:
- ./vendor/cache
when:
branch:
- master
- name: rspec
image: guildeducation/rails:2.7.2-14.20.0
environment:
RAILS_ENV: test
REDIS_URL: redis://redis:6379/0
RS_REDIS_URL: redis://redis:6379/1
commands:
- bundle config unset deployment
- bundle config set cache_all 'true'
- bundle config set cache_path 'vendor/cache'
- bundle config set with 'development test'
- bundle install --jobs=3 --retry=3
- yarn install
- rake css:build
- bundle exec rspec
- name: rebuild-cache
image: drillster/drone-volume-cache
volumes:
- name: cache
path: /cache
settings:
rebuild: true
mount:
- ./vendor/cache
when:
branch:
- master
services:
- name: redis
image: redis
volumes:
- name: cache
host:
path: /var/lib/drone/tmp
---
kind: signature
hmac: f9a8cf97f6596625721365f6238f6f298aa5a7a4de10c3fb61c57202ae9d1ee1
...

View File

@@ -1,8 +1,46 @@
LDAP_HOST=192.168.33.10
PRIMARY_DOMAIN=kosmos.org
AKKOUNTS_DOMAIN=accounts.example.com
SMTP_SERVER=smtp.example.com
SMTP_PORT=587
SMTP_LOGIN=accounts
SMTP_PASSWORD=123abc
SMTP_FROM_ADDRESS=accounts@example.com
SMTP_DOMAIN=example.com
SMTP_AUTH_METHOD=plain
SMTP_ENABLE_STARTTLS=auto
LDAP_HOST=localhost
LDAP_PORT=389
#
# Production LDAP server:
#
# LDAP_HOST=ldap.kosmos.org
# LDAP_PORT=636
# LDAP_USE_TLS=true
LDAP_ADMIN_PASSWORD=passthebutter
LDAP_SUFFIX='dc=kosmos,dc=org'
REDIS_URL='redis://localhost:6379/1'
WEBHOOKS_ALLOWED_IPS='10.1.1.163'
DISCOURSE_PUBLIC_URL='https://community.kosmos.org'
DISCOURSE_CONNECT_SECRET='discourse_connect_ftw'
DRONECI_PUBLIC_URL='https://drone.kosmos.org'
GITEA_PUBLIC_URL='https://gitea.kosmos.org'
MASTODON_PUBLIC_URL='https://kosmos.social'
MEDIAWIKI_PUBLIC_URL='https://wiki.kosmos.org'
RS_STORAGE_URL='https://storage.kosmos.org'
RS_REDIS_URL='redis://localhost:6379/2'
EJABBERD_ADMIN_URL='https://xmpp.kosmos.org/admin'
EJABBERD_API_URL='https://xmpp.kosmos.org/api'
BTCPAY_API_URL='http://localhost:23001/api/v1'
LNDHUB_API_URL='http://localhost:3023'
LNDHUB_PUBLIC_URL='https://lndhub.kosmos.org'
LNDHUB_PUBLIC_KEY='0123d3be18617f39cf645851e3ba63f51fc13f0bb09e3bb25e6fd4de556486d946'
LNDHUB_ADMIN_UI=true
LNDHUB_PG_HOST=localhost
LNDHUB_PG_PORT=5432
LNDHUB_PG_DATABASE=lndhub
LNDHUB_PG_USERNAME=lndhub
LNDHUB_PG_PASSWORD=''

19
.env.test Normal file
View File

@@ -0,0 +1,19 @@
PRIMARY_DOMAIN=kosmos.org
REDIS_URL='redis://localhost:6379/0'
DISCOURSE_PUBLIC_URL='http://discourse.example.com'
DISCOURSE_CONNECT_SECRET='discourse_connect_ftw'
EJABBERD_API_URL='http://xmpp.example.com/api'
BTCPAY_API_URL='http://btcpay.example.com/api/v1'
LNDHUB_API_URL='http://localhost:3026'
LNDHUB_PUBLIC_URL='https://lndhub.kosmos.org'
LNDHUB_PUBLIC_KEY='024cd3be18617f39cf645851e3ba63f51fc13f0bb09e3bb25e6fd4de556486d946'
RS_STORAGE_URL='https://storage.kosmos.org'
RS_REDIS_URL='redis://localhost:6379/1'
WEBHOOKS_ALLOWED_IPS='10.1.1.23'

View File

@@ -0,0 +1,14 @@
name-template: 'v$RESOLVED_VERSION'
tag-template: 'v$RESOLVED_VERSION'
version-resolver:
major:
labels:
- 'release/major'
minor:
labels:
- 'release/minor'
- 'feature'
patch:
labels:
- 'release/patch'
default: patch

View File

@@ -0,0 +1,11 @@
name: Release Drafter
on:
pull_request:
types: [closed]
jobs:
release_drafter_job:
name: Update release notes draft
runs-on: ubuntu-latest
steps:
- name: Release Drafter
uses: https://github.com/raucao/gitea-release-drafter@dev

7
.gitignore vendored
View File

@@ -39,3 +39,10 @@ yarn-debug.log*
# Ignore local dotenv config file
.env
.env.development
# Ignore redis dumps from sidekiq
dump.rdb
/app/assets/builds/*
!/app/assets/builds/.keep

View File

@@ -1 +1 @@
2.6.1
2.7.2

21
Dockerfile Normal file
View File

@@ -0,0 +1,21 @@
# syntax=docker/dockerfile:1
FROM ruby:2.7.6
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
RUN apt-get update -qq && apt-get install -y --no-install-recommends curl \
ldap-utils tini
RUN curl -fsSL https://deb.nodesource.com/setup_lts.x | bash -
RUN apt-get update && apt-get install -y nodejs
WORKDIR /akkounts
COPY ["Gemfile", "Gemfile.lock", "package.json", "./"]
RUN bundle install
RUN gem install foreman
RUN npm install -g yarn
RUN yarn install
ENTRYPOINT ["/usr/bin/tini", "--"]
EXPOSE 3000

76
Gemfile
View File

@@ -1,20 +1,22 @@
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
ruby '2.6.1'
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 6.0.3', '>= 6.0.3.4'
# Use sqlite3 as the database for Active Record
gem 'sqlite3', '~> 1.4'
gem 'rails', '~> 7.0.2'
# Use Puma as the app server
gem 'puma', '~> 4.1'
# Use SCSS for stylesheets
gem 'sass-rails', '>= 6'
# Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker
gem 'webpacker', '~> 4.0'
# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
gem 'turbolinks', '~> 5'
# View components
gem "view_component"
# Separate dependency since Rails 7.0
gem 'sprockets-rails'
# Allows custom JS build tasks to integrate with the asset pipeline
gem 'cssbundling-rails'
# Use JavaScript with ESM import maps [https://github.com/rails/importmap-rails]
gem "importmap-rails"
# Hotwire's SPA-like page accelerator [https://turbo.hotwired.dev]
gem "turbo-rails"
# Hotwire's modest JavaScript framework [https://stimulus.hotwired.dev]
gem "stimulus-rails"
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.7'
# Use Redis adapter to run Action Cable in production
@@ -22,38 +24,70 @@ gem 'jbuilder', '~> 2.7'
# Use Active Model has_secure_password
# gem 'bcrypt', '~> 3.1.7'
# Reduces boot times through caching; required in config/boot.rb
gem 'bootsnap', '>= 1.4.2', require: false
# Configuration
gem 'dotenv-rails'
gem 'dotenv-rails', groups: [:development, :test]
# Security
gem 'lockbox'
# Authentication
gem 'warden'
gem 'devise'
gem 'devise', '~> 4.9.0'
gem 'devise_ldap_authenticatable'
gem 'net-ldap'
# Utilities
gem "rqrcode", "~> 2.0"
gem 'rails-settings-cached', '~> 2.8.3'
gem 'pagy', '~> 6.0', '>= 6.0.2'
gem 'flipper'
gem 'flipper-active_record'
gem 'flipper-ui'
# HTTP requests
gem 'faraday'
# Background/scheduled jobs
gem 'sidekiq', '< 7'
gem 'sidekiq-scheduler'
# Monitoring
gem "sentry-ruby"
gem "sentry-rails"
# Services
gem 'discourse_api'
gem "lnurl"
gem 'nostr', git: 'https://gitea.kosmos.org/kosmos/nostr-gem.git', branch: 'feature/ruby_2.7_compat'
group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
# Use sqlite3 as the database for Active Record
gem 'sqlite3', '~> 1.4'
gem 'rspec-rails'
gem 'rails-controller-testing'
gem "byebug", "~> 11.1"
end
group :development do
# Access an interactive console on exception pages or by calling 'console' anywhere in the code.
gem 'web-console', '>= 3.3.0'
gem 'listen', '~> 3.2'
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
gem 'spring'
gem 'spring-watcher-listen', '~> 2.0.0'
gem 'letter_opener'
gem 'letter_opener_web'
gem 'faker'
gem 'solargraph'
end
group :test do
gem 'rspec-rails'
gem 'factory_bot_rails'
gem 'capybara'
gem 'database_cleaner'
gem 'webmock'
end
group :production do
# Use postgresql as the database for Active Record
gem 'pg', '~> 1.2.3'
end
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

View File

@@ -1,81 +1,122 @@
GIT
remote: https://gitea.kosmos.org/kosmos/nostr-gem.git
revision: 596529d9eb50d13b3f385245636698fccf37b442
branch: feature/ruby_2.7_compat
specs:
nostr (0.4.0)
bech32 (~> 1.3)
bip-schnorr (~> 0.4)
ecdsa (~> 1.2)
event_emitter (~> 0.2)
faye-websocket (~> 0.11)
json (~> 2.6)
GEM
remote: https://rubygems.org/
specs:
actioncable (6.0.3.4)
actionpack (= 6.0.3.4)
actioncable (7.0.5)
actionpack (= 7.0.5)
activesupport (= 7.0.5)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
actionmailbox (6.0.3.4)
actionpack (= 6.0.3.4)
activejob (= 6.0.3.4)
activerecord (= 6.0.3.4)
activestorage (= 6.0.3.4)
activesupport (= 6.0.3.4)
actionmailbox (7.0.5)
actionpack (= 7.0.5)
activejob (= 7.0.5)
activerecord (= 7.0.5)
activestorage (= 7.0.5)
activesupport (= 7.0.5)
mail (>= 2.7.1)
actionmailer (6.0.3.4)
actionpack (= 6.0.3.4)
actionview (= 6.0.3.4)
activejob (= 6.0.3.4)
net-imap
net-pop
net-smtp
actionmailer (7.0.5)
actionpack (= 7.0.5)
actionview (= 7.0.5)
activejob (= 7.0.5)
activesupport (= 7.0.5)
mail (~> 2.5, >= 2.5.4)
net-imap
net-pop
net-smtp
rails-dom-testing (~> 2.0)
actionpack (6.0.3.4)
actionview (= 6.0.3.4)
activesupport (= 6.0.3.4)
rack (~> 2.0, >= 2.0.8)
actionpack (7.0.5)
actionview (= 7.0.5)
activesupport (= 7.0.5)
rack (~> 2.0, >= 2.2.4)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
actiontext (6.0.3.4)
actionpack (= 6.0.3.4)
activerecord (= 6.0.3.4)
activestorage (= 6.0.3.4)
activesupport (= 6.0.3.4)
actiontext (7.0.5)
actionpack (= 7.0.5)
activerecord (= 7.0.5)
activestorage (= 7.0.5)
activesupport (= 7.0.5)
globalid (>= 0.6.0)
nokogiri (>= 1.8.5)
actionview (6.0.3.4)
activesupport (= 6.0.3.4)
actionview (7.0.5)
activesupport (= 7.0.5)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
activejob (6.0.3.4)
activesupport (= 6.0.3.4)
activejob (7.0.5)
activesupport (= 7.0.5)
globalid (>= 0.3.6)
activemodel (6.0.3.4)
activesupport (= 6.0.3.4)
activerecord (6.0.3.4)
activemodel (= 6.0.3.4)
activesupport (= 6.0.3.4)
activestorage (6.0.3.4)
actionpack (= 6.0.3.4)
activejob (= 6.0.3.4)
activerecord (= 6.0.3.4)
marcel (~> 0.3.1)
activesupport (6.0.3.4)
activemodel (7.0.5)
activesupport (= 7.0.5)
activerecord (7.0.5)
activemodel (= 7.0.5)
activesupport (= 7.0.5)
activestorage (7.0.5)
actionpack (= 7.0.5)
activejob (= 7.0.5)
activerecord (= 7.0.5)
activesupport (= 7.0.5)
marcel (~> 1.0)
mini_mime (>= 1.1.0)
activesupport (7.0.5)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
zeitwerk (~> 2.2, >= 2.2.2)
addressable (2.7.0)
public_suffix (>= 2.0.2, < 5.0)
bcrypt (3.1.16)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
addressable (2.8.4)
public_suffix (>= 2.0.2, < 6.0)
ast (2.4.2)
backport (1.2.0)
bcrypt (3.1.18)
bech32 (1.3.0)
thor (>= 1.1.0)
benchmark (0.2.1)
bindex (0.8.1)
bootsnap (1.5.0)
msgpack (~> 1.0)
bip-schnorr (0.6.0)
ecdsa_ext (~> 0.5.0)
builder (3.2.4)
byebug (11.1.3)
capybara (3.33.0)
capybara (3.39.2)
addressable
matrix
mini_mime (>= 0.1.3)
nokogiri (~> 1.8)
rack (>= 1.6.0)
rack-test (>= 0.6.3)
regexp_parser (~> 1.5)
regexp_parser (>= 1.5, < 3.0)
xpath (~> 3.2)
concurrent-ruby (1.1.7)
chunky_png (1.4.0)
concurrent-ruby (1.2.2)
connection_pool (2.4.1)
crack (0.4.5)
rexml
crass (1.0.6)
database_cleaner (1.8.5)
devise (4.7.3)
cssbundling-rails (1.1.2)
railties (>= 6.0.0)
database_cleaner (2.0.2)
database_cleaner-active_record (>= 2, < 3)
database_cleaner-active_record (2.1.0)
activerecord (>= 5.a)
database_cleaner-core (~> 2.0.0)
database_cleaner-core (2.0.1)
date (3.3.3)
devise (4.9.2)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 4.1.0)
@@ -84,192 +125,347 @@ GEM
devise_ldap_authenticatable (0.8.7)
devise (>= 3.4.1)
net-ldap (>= 0.16.0)
diff-lcs (1.4.4)
dotenv (2.7.2)
dotenv-rails (2.7.2)
dotenv (= 2.7.2)
railties (>= 3.2, < 6.1)
erubi (1.9.0)
factory_bot (6.1.0)
activesupport (>= 5.0.0)
factory_bot_rails (6.1.0)
factory_bot (~> 6.1.0)
railties (>= 5.0.0)
ffi (1.13.1)
globalid (0.4.2)
activesupport (>= 4.2.0)
i18n (1.8.5)
concurrent-ruby (~> 1.0)
jbuilder (2.10.1)
activesupport (>= 5.0.0)
launchy (2.4.3)
addressable (~> 2.3)
letter_opener (1.7.0)
launchy (~> 2.2)
letter_opener_web (1.3.4)
actionmailer (>= 3.2)
letter_opener (~> 1.0)
diff-lcs (1.5.0)
discourse_api (2.0.1)
faraday (~> 2.7)
faraday-follow_redirects
faraday-multipart
rack (>= 1.6)
dotenv (2.8.1)
dotenv-rails (2.8.1)
dotenv (= 2.8.1)
railties (>= 3.2)
listen (3.2.1)
e2mmap (0.1.0)
ecdsa (1.2.0)
ecdsa_ext (0.5.0)
ecdsa (~> 1.2.0)
erubi (1.12.0)
et-orbi (1.2.7)
tzinfo
event_emitter (0.2.6)
eventmachine (1.2.7)
factory_bot (6.2.1)
activesupport (>= 5.0.0)
factory_bot_rails (6.2.0)
factory_bot (~> 6.2.0)
railties (>= 5.0.0)
faker (3.2.0)
i18n (>= 1.8.11, < 2)
faraday (2.7.6)
faraday-net_http (>= 2.0, < 3.1)
ruby2_keywords (>= 0.0.4)
faraday-follow_redirects (0.3.0)
faraday (>= 1, < 3)
faraday-multipart (1.0.4)
multipart-post (~> 2)
faraday-net_http (3.0.2)
faye-websocket (0.11.2)
eventmachine (>= 0.12.0)
websocket-driver (>= 0.5.1)
ffi (1.15.5)
flipper (0.28.0)
concurrent-ruby (< 2)
flipper-active_record (0.28.0)
activerecord (>= 4.2, < 8)
flipper (~> 0.28.0)
flipper-ui (0.28.0)
erubi (>= 1.0.0, < 2.0.0)
flipper (~> 0.28.0)
rack (>= 1.4, < 3)
rack-protection (>= 1.5.3, <= 4.0.0)
sanitize (< 7)
fugit (1.8.1)
et-orbi (~> 1, >= 1.2.7)
raabro (~> 1.4)
globalid (1.1.0)
activesupport (>= 5.0)
hashdiff (1.0.1)
i18n (1.14.1)
concurrent-ruby (~> 1.0)
importmap-rails (1.1.6)
actionpack (>= 6.0.0)
railties (>= 6.0.0)
jaro_winkler (1.5.6)
jbuilder (2.11.5)
actionview (>= 5.0.0)
activesupport (>= 5.0.0)
json (2.6.3)
kramdown (2.4.0)
rexml
kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0)
launchy (2.5.2)
addressable (~> 2.8)
letter_opener (1.8.1)
launchy (>= 2.2, < 3)
letter_opener_web (2.0.0)
actionmailer (>= 5.2)
letter_opener (~> 1.7)
railties (>= 5.2)
rexml
listen (3.8.0)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
loofah (2.7.0)
lnurl (1.0.1)
bech32 (~> 1.1)
lockbox (1.2.0)
loofah (2.21.3)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
mail (2.7.1)
nokogiri (>= 1.12.0)
mail (2.8.1)
mini_mime (>= 0.1.1)
marcel (0.3.3)
mimemagic (~> 0.3.2)
net-imap
net-pop
net-smtp
marcel (1.0.2)
matrix (0.4.2)
method_source (1.0.0)
mimemagic (0.3.5)
mini_mime (1.0.2)
mini_portile2 (2.4.0)
minitest (5.14.2)
msgpack (1.3.3)
net-ldap (0.16.3)
nio4r (2.5.4)
nokogiri (1.10.10)
mini_portile2 (~> 2.4.0)
mini_mime (1.1.2)
minitest (5.18.0)
multipart-post (2.3.0)
net-imap (0.3.6)
date
net-protocol
net-ldap (0.18.0)
net-pop (0.1.2)
net-protocol
net-protocol (0.2.1)
timeout
net-smtp (0.3.3)
net-protocol
nio4r (2.5.9)
nokogiri (1.15.2-arm64-darwin)
racc (~> 1.4)
nokogiri (1.15.2-x86_64-linux)
racc (~> 1.4)
orm_adapter (0.5.0)
public_suffix (4.0.6)
puma (4.3.6)
pagy (6.0.4)
parallel (1.23.0)
parser (3.2.2.3)
ast (~> 2.4.1)
racc
pg (1.2.3)
public_suffix (5.0.1)
puma (4.3.12)
nio4r (~> 2.0)
rack (2.2.3)
rack-proxy (0.6.5)
raabro (1.4.0)
racc (1.7.1)
rack (2.2.7)
rack-protection (3.0.6)
rack
rack-test (1.1.0)
rack (>= 1.0, < 3)
rails (6.0.3.4)
actioncable (= 6.0.3.4)
actionmailbox (= 6.0.3.4)
actionmailer (= 6.0.3.4)
actionpack (= 6.0.3.4)
actiontext (= 6.0.3.4)
actionview (= 6.0.3.4)
activejob (= 6.0.3.4)
activemodel (= 6.0.3.4)
activerecord (= 6.0.3.4)
activestorage (= 6.0.3.4)
activesupport (= 6.0.3.4)
bundler (>= 1.3.0)
railties (= 6.0.3.4)
sprockets-rails (>= 2.0.0)
rack-test (2.1.0)
rack (>= 1.3)
rails (7.0.5)
actioncable (= 7.0.5)
actionmailbox (= 7.0.5)
actionmailer (= 7.0.5)
actionpack (= 7.0.5)
actiontext (= 7.0.5)
actionview (= 7.0.5)
activejob (= 7.0.5)
activemodel (= 7.0.5)
activerecord (= 7.0.5)
activestorage (= 7.0.5)
activesupport (= 7.0.5)
bundler (>= 1.15.0)
railties (= 7.0.5)
rails-controller-testing (1.0.5)
actionpack (>= 5.0.1.rc1)
actionview (>= 5.0.1.rc1)
activesupport (>= 5.0.1.rc1)
rails-dom-testing (2.0.3)
activesupport (>= 4.2.0)
nokogiri (>= 1.6)
rails-html-sanitizer (1.3.0)
loofah (~> 2.3)
railties (6.0.3.4)
actionpack (= 6.0.3.4)
activesupport (= 6.0.3.4)
rails-html-sanitizer (1.6.0)
loofah (~> 2.21)
nokogiri (~> 1.14)
rails-settings-cached (2.8.3)
activerecord (>= 5.0.0)
railties (>= 5.0.0)
railties (7.0.5)
actionpack (= 7.0.5)
activesupport (= 7.0.5)
method_source
rake (>= 0.8.7)
thor (>= 0.20.3, < 2.0)
rake (13.0.1)
rb-fsevent (0.10.4)
rake (>= 12.2)
thor (~> 1.0)
zeitwerk (~> 2.5)
rainbow (3.1.1)
rake (13.0.6)
rb-fsevent (0.11.2)
rb-inotify (0.10.1)
ffi (~> 1.0)
regexp_parser (1.8.2)
responders (3.0.1)
actionpack (>= 5.0)
rbs (2.8.4)
redis (4.8.1)
regexp_parser (2.8.1)
responders (3.1.0)
actionpack (>= 5.2)
railties (>= 5.2)
reverse_markdown (2.1.1)
nokogiri
rexml (3.2.5)
rqrcode (2.2.0)
chunky_png (~> 1.0)
rqrcode_core (~> 1.0)
rqrcode_core (1.2.0)
rspec-core (3.12.2)
rspec-support (~> 3.12.0)
rspec-expectations (3.12.3)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.12.0)
rspec-mocks (3.12.5)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.12.0)
rspec-rails (6.0.3)
actionpack (>= 6.1)
activesupport (>= 6.1)
railties (>= 6.1)
rspec-core (~> 3.12)
rspec-expectations (~> 3.12)
rspec-mocks (~> 3.12)
rspec-support (~> 3.12)
rspec-support (3.12.0)
rubocop (1.52.1)
json (~> 2.3)
parallel (~> 1.10)
parser (>= 3.2.2.3)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0)
rexml (>= 3.2.5, < 4.0)
rubocop-ast (>= 1.28.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 3.0)
rubocop-ast (1.29.0)
parser (>= 3.2.1.0)
ruby-progressbar (1.13.0)
ruby2_keywords (0.0.5)
rufus-scheduler (3.9.1)
fugit (~> 1.1, >= 1.1.6)
sanitize (6.0.1)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
sentry-rails (5.9.0)
railties (>= 5.0)
rspec-core (3.10.0)
rspec-support (~> 3.10.0)
rspec-expectations (3.10.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.10.0)
rspec-mocks (3.10.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.10.0)
rspec-rails (4.0.1)
actionpack (>= 4.2)
activesupport (>= 4.2)
railties (>= 4.2)
rspec-core (~> 3.9)
rspec-expectations (~> 3.9)
rspec-mocks (~> 3.9)
rspec-support (~> 3.9)
rspec-support (3.10.0)
sass-rails (6.0.0)
sassc-rails (~> 2.1, >= 2.1.1)
sassc (2.4.0)
ffi (~> 1.9)
sassc-rails (2.1.2)
railties (>= 4.0.0)
sassc (>= 2.0)
sprockets (> 3.0)
sprockets-rails
tilt
spring (2.1.1)
spring-watcher-listen (2.0.1)
listen (>= 2.7, < 4.0)
spring (>= 1.2, < 3.0)
sprockets (4.0.2)
sentry-ruby (~> 5.9.0)
sentry-ruby (5.9.0)
concurrent-ruby (~> 1.0, >= 1.0.2)
sidekiq (6.5.9)
connection_pool (>= 2.2.5, < 3)
rack (~> 2.0)
redis (>= 4.5.0, < 5)
sidekiq-scheduler (5.0.3)
rufus-scheduler (~> 3.2)
sidekiq (>= 6, < 8)
tilt (>= 1.4.0)
solargraph (0.49.0)
backport (~> 1.2)
benchmark
bundler (~> 2.0)
diff-lcs (~> 1.4)
e2mmap
jaro_winkler (~> 1.5)
kramdown (~> 2.3)
kramdown-parser-gfm (~> 1.1)
parser (~> 3.0)
rbs (~> 2.0)
reverse_markdown (~> 2.0)
rubocop (~> 1.38)
thor (~> 1.0)
tilt (~> 2.0)
yard (~> 0.9, >= 0.9.24)
sprockets (4.2.0)
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
sprockets-rails (3.2.2)
actionpack (>= 4.0)
activesupport (>= 4.0)
rack (>= 2.2.4, < 4)
sprockets-rails (3.4.2)
actionpack (>= 5.2)
activesupport (>= 5.2)
sprockets (>= 3.0.0)
sqlite3 (1.4.2)
thor (1.0.1)
thread_safe (0.3.6)
tilt (2.0.10)
turbolinks (5.2.1)
turbolinks-source (~> 5.2)
turbolinks-source (5.2.0)
tzinfo (1.2.7)
thread_safe (~> 0.1)
sqlite3 (1.6.3-arm64-darwin)
sqlite3 (1.6.3-x86_64-linux)
stimulus-rails (1.2.1)
railties (>= 6.0.0)
thor (1.2.2)
tilt (2.2.0)
timeout (0.3.2)
turbo-rails (1.4.0)
actionpack (>= 6.0.0)
activejob (>= 6.0.0)
railties (>= 6.0.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unicode-display_width (2.4.2)
view_component (3.2.0)
activesupport (>= 5.2.0, < 8.0)
concurrent-ruby (~> 1.0)
method_source (~> 1.0)
warden (1.2.9)
rack (>= 2.0.9)
web-console (4.1.0)
web-console (4.2.0)
actionview (>= 6.0.0)
activemodel (>= 6.0.0)
bindex (>= 0.4.0)
railties (>= 6.0.0)
webpacker (4.3.0)
activesupport (>= 4.2)
rack-proxy (>= 0.6.1)
railties (>= 4.2)
websocket-driver (0.7.3)
webmock (3.18.1)
addressable (>= 2.8.0)
crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0)
websocket-driver (0.7.5)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
xpath (3.2.0)
nokogiri (~> 1.8)
zeitwerk (2.4.1)
yard (0.9.34)
zeitwerk (2.6.8)
PLATFORMS
ruby
arm64-darwin-22
x86_64-linux
DEPENDENCIES
bootsnap (>= 1.4.2)
byebug
byebug (~> 11.1)
capybara
cssbundling-rails
database_cleaner
devise
devise (~> 4.9.0)
devise_ldap_authenticatable
discourse_api
dotenv-rails
factory_bot_rails
faker
faraday
flipper
flipper-active_record
flipper-ui
importmap-rails
jbuilder (~> 2.7)
letter_opener
letter_opener_web
listen (~> 3.2)
lnurl
lockbox
net-ldap
nostr!
pagy (~> 6.0, >= 6.0.2)
pg (~> 1.2.3)
puma (~> 4.1)
rails (~> 6.0.3, >= 6.0.3.4)
rails (~> 7.0.2)
rails-controller-testing
rails-settings-cached (~> 2.8.3)
rqrcode (~> 2.0)
rspec-rails
sass-rails (>= 6)
spring
spring-watcher-listen (~> 2.0.0)
sentry-rails
sentry-ruby
sidekiq (< 7)
sidekiq-scheduler
solargraph
sprockets-rails
sqlite3 (~> 1.4)
turbolinks (~> 5)
stimulus-rails
turbo-rails
tzinfo-data
view_component
warden
web-console (>= 3.3.0)
webpacker (~> 4.0)
RUBY VERSION
ruby 2.6.1p33
webmock
BUNDLED WITH
2.0.2
2.3.7

661
LICENSE Normal file
View File

@@ -0,0 +1,661 @@
GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
Copyright (C) 2020 Kosmos Contributors <https://kosmos.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
our General Public Licenses are intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
Developers that use our General Public Licenses protect your rights
with two steps: (1) assert copyright on the software, and (2) offer
you this License which gives you legal permission to copy, distribute
and/or modify the software.
A secondary benefit of defending all users' freedom is that
improvements made in alternate versions of the program, if they
receive widespread use, become available for other developers to
incorporate. Many developers of free software are heartened and
encouraged by the resulting cooperation. However, in the case of
software used on network servers, this result may fail to come about.
The GNU General Public License permits making a modified version and
letting the public access it on a server without ever releasing its
source code to the public.
The GNU Affero General Public License is designed specifically to
ensure that, in such cases, the modified source code becomes available
to the community. It requires the operator of a network server to
provide the source code of the modified version running there to the
users of that server. Therefore, public use of a modified version, on
a publicly accessible server, gives the public access to the source
code of the modified version.
An older license, called the Affero General Public License and
published by Affero, was designed to accomplish similar goals. This is
a different license, not a version of the Affero GPL, but Affero has
released a new version of the Affero GPL which permits relicensing under
this license.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU Affero General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Remote Network Interaction; Use with the GNU General Public License.
Notwithstanding any other provision of this License, if you modify the
Program, your modified version must prominently offer all users
interacting with it remotely through a computer network (if your version
supports such interaction) an opportunity to receive the Corresponding
Source of your version by providing access to the Corresponding Source
from a network server at no charge, through some standard or customary
means of facilitating copying of software. This Corresponding Source
shall include the Corresponding Source for any work covered by version 3
of the GNU General Public License that is incorporated pursuant to the
following paragraph.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the work with which it is combined will remain governed by version
3 of the GNU General Public License.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU Affero General Public License from time to time. Such new versions
will be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU Affero General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU Affero General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU Affero General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If your software can interact with users remotely through a computer
network, you should also make sure that it provides a way for users to
get its source. For example, if your program is a web application, its
interface could display a "Source" link that leads users to an archive
of the code. There are many ways you could offer source, and different
solutions will be better for different programs; see section 13 for the
specific requirements.
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU AGPL, see
<https://www.gnu.org/licenses/>.

2
Procfile.dev Normal file
View File

@@ -0,0 +1,2 @@
web: bin/rails server -b 0.0.0.0 -p 3000
css: yarn build:css --watch

133
README.md
View File

@@ -1,28 +1,135 @@
# README
[![Build Status](https://drone.kosmos.org/api/badges/kosmos/akkounts/status.svg)](https://drone.kosmos.org/kosmos/akkounts)
This README would normally document whatever steps are necessary to get the
application up and running.
# Akkounts
Things you may want to cover:
This app allows Kosmos/LDAP users to manage their accounts, including
credentials, invites, donations, etc..
* Ruby version
## Development
* System dependencies
### Quick Start
* Configuration
The easiest way to get a working development setup is using Docker Compose like
so:
* Database creation
1. Make sure [Docker Compose is installed][1] and Docker is running (included in
Docker Desktop)
3. Run `docker compose up` and wait until 389ds announces its successful start
in the log output
4. `docker-compose exec ldap dsconf localhost backend create --suffix="dc=kosmos,dc=org" --be-name="dev"`
5. `docker compose run web rails ldap:setup`
6. `docker compose run web rails db:setup`
* Database initialization
After these steps, you should have a working Rails app with a handful of test
users running on [http://localhost:3000](http://localhost:3000).
Log in with username "admin" and password "admin is admin". All users listed on
[http://localhost:3000/admin/users](http://localhost:3000/admin/users)
have the password "user is user".
* How to run the test suite
### Rails app
* Services (job queues, cache servers, search engines, etc.)
Installing dependencies:
* Deployment instructions
bundle install
yarn install
* ...
Setting up local database (SQLite):
bundle exec rails db:create
bundle exec rails db:migrate
Running the dev server and auto-building CSS files on change:
bin/dev
Running the background workers (requires Redis):
bundle exec sidekiq -C config/sidekiq.yml
Running all specs:
bundle exec rspec
### Docker (Compose)
There is a working Docker Compose config file, which define a number of services including
an app server for Rails as well as a local 389ds (LDAP) server.
For Rails developers, you probably just want to start the LDAP server: `docker-compose up ldap`,
listening on port 389 on your machine.
You can pick and choose your services adding them by name (listed in `docker-compose.yml`) at
the end of the docker compose command. eg. `docker compose up ldap redis`
#### LDAP server
After creating the Docker container for the first time (or after deleting it),
you need to run the following command once, in order to create the dirsrv
back-end:
docker-compose exec ldap dsconf localhost backend create --suffix="dc=kosmos,dc=org" --be-name="dev"
Now you can seed the back-end with data using this Rails task:
bundle exec rails ldap:setup
The setup task will first delete any existing entries in the directory tree
("dc=kosmos,dc=org"), and then create our development entries.
Note that all 389ds data is stored in `tmp/389ds`. So if you want to start over
with a fresh installation, delete both that directory as well as the container.
### Adding npm modules to use with Stimulus controllers
The following command downloads the specified npm module to `vendor/javascript`
and adds an entry for it to `config/importmap.rb`.
bin/importmap pin bech32 --download
### Solargraph
[Solargraph](https://solargraph.org/) is a Ruby language server, which you may
use with your editor to add features like auto-completion and syntax
validation. You can add inline documentation for bundled gems with this
command:
bundle exec yard gems
## Documentation
### Rails
* [Ruby on Rails](https://guides.rubyonrails.org/)
* [Pagination](https://ddnexus.github.io/pagy/)
### Front-end
* [Tailwind CSS](https://tailwindcss.com/)
* [Sass](https://sass-lang.com/documentation)
* [Stimulus](https://stimulus.hotwired.dev/handbook/)
* [Tailwind Stimulus Components](https://github.com/excid3/tailwindcss-stimulus-components)
### Testing
* [RSpec](https://rspec.info/documentation/)
* [Capybara](https://rubydoc.info/github/teamcapybara/capybara/master)
### LDAP / Auth
* [devise_ldap_authenticatable](https://github.com/cschiewek/devise_ldap_authenticatable)
* [net/ldap](https://www.rubydoc.info/gems/net-ldap/Net/LDAP)
### Asynchronous jobs/workers
* [Sidekiq](https://github.com/mperham/sidekiq/wiki/)
* [ActiveJob](https://github.com/mperham/sidekiq/wiki/Active-Job)
### Feature Flags
* [Flipper](https://www.flippercloud.io/docs/get-started/self-hosted)
## License
[GNU Affero General Public License v3.0](https://choosealicense.com/licenses/agpl-3.0/)
[1]: https://docs.docker.com/compose/install/

View File

@@ -1,2 +1,4 @@
//= link_tree ../images
//= link_directory ../stylesheets .css
//= link_tree ../../javascript .js
//= link_tree ../builds
//= link_tree ../../../vendor/javascript .js

View File

@@ -1,13 +0,0 @@
html, body, h1, h2, h3, h4, h5, h6, p, pre, a, dl, dt, dd, ol, ul, li {
font-size: 100%;
vertical-align: baseline;
background: transparent;
box-sizing: border-box;
overflow: visible;
margin: 0;
padding: 0;
}
body {
line-height: 1;
}

View File

@@ -1,15 +0,0 @@
/*
* This is a manifest file that'll be compiled into application.css, which will include all the files
* listed below.
*
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's
* vendor/assets/stylesheets directory can be referenced here using a relative path.
*
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
* files in this directory. Styles in this file should be added after the last require_* statement.
* It is generally better to create a new file per style scope.
*
*= require_tree .
*= require_self
*/

View File

@@ -0,0 +1,13 @@
@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";
@import "components/animations";
@import "components/base";
@import "components/buttons";
@import "components/dashboard_services";
@import "components/forms";
@import "components/links";
@import "components/notifications";
@import "components/pagination";
@import "components/tables";

View File

@@ -0,0 +1,16 @@
@keyframes scaleIn {
from {
transform: scale(0.5);
opacity: 0;
}
to {
transform: scale(1);
opacity: 1;
}
}
.animate-scale-in {
animation-name: scaleIn;
animation-duration: 0.15s;
animation-timing-function: cubic-bezier(0.2, 0, 0.13, 1);
}

View File

@@ -0,0 +1,58 @@
@layer base {
html {
font-size: 14px;
}
body {
@apply leading-none bg-cover bg-fixed;
background-image: linear-gradient(35deg, rgba(255,0,255,0.2) 0, rgba(13,79,153,0.8) 100%), url('/img/bg-1.jpg');
}
body#admin {
background-image: linear-gradient(35deg, rgba(255,0,255,0.2) 0, rgba(153,12,14,0.9) 100%), url('/img/bg-1.jpg');
}
h1 {
@apply text-3xl uppercase;
}
h2 {
@apply text-2xl mb-8;
}
h3 {
@apply text-xl mb-6;
}
h4 {
@apply font-bold mb-4 leading-6;
}
main section {
@apply pt-8 sm:pt-12;
}
main section:first-of-type {
@apply pt-0;
}
main p {
@apply mb-4 leading-6;
}
main p:last-child {
@apply mb-0;
}
main ul {
@apply mb-6;
}
main ul:last-child {
@apply mb-0;
}
main ul li {
@apply leading-6;
}
}

View File

@@ -0,0 +1,44 @@
@layer components {
.btn {
@apply inline-block font-semibold rounded-md leading-none cursor-pointer text-center
transition-colors duration-75 focus:outline-none focus:ring-4;
}
.btn-md {
@apply btn;
@apply py-3 px-6;
}
.btn-sm {
@apply btn;
@apply py-1 px-2 text-sm;
}
.btn-icon {
@apply py-2 px-3;
}
.btn-outline {
@apply py-2 border-2 border-gray-100 hover:bg-gray-100;
}
.btn-gray {
@apply bg-gray-100 hover:bg-gray-200
focus:ring-gray-300 focus:ring-opacity-75;
}
.btn-blue {
@apply bg-blue-500 hover:bg-blue-600 text-white
focus:ring-blue-400 focus:ring-opacity-75;
}
.btn-red {
@apply bg-red-600 hover:bg-red-700 text-white
focus:ring-red-500 focus:ring-opacity-75;
}
.btn:disabled {
@apply bg-gray-100 hover:bg-gray-200 text-gray-400
focus:ring-gray-300 focus:ring-opacity-75;
}
}

View File

@@ -0,0 +1,5 @@
@layer components {
.services > div > a {
background-image: linear-gradient(110deg, rgba(255,255,255,0.99) 0, rgba(255,255,255,0.88) 100%);
}
}

View File

@@ -0,0 +1,25 @@
@layer components {
input[type=text], input[type=email], input[type=password],
input[type=number], select, textarea {
@apply rounded-md bg-gray-100 focus:bg-white
border-transparent focus:border-transparent focus:ring-2
focus:ring-blue-600 focus:ring-opacity-75;
}
input[type=text]:disabled,
input[type=email]:disabled {
@apply text-gray-700;
}
input.field_with_errors {
@apply border-b-red-600;
}
.field_with_errors {
@apply inline-block;
}
.error-msg {
@apply text-red-700;
}
}

View File

@@ -0,0 +1,8 @@
@layer components {
.ks-text-link {
@apply text-blue-600;
&:hover { @apply underline; }
&:visited { @apply text-indigo-600; }
&:active { @apply text-red-600; }
}
}

View File

@@ -0,0 +1,39 @@
@layer components {
@keyframes notification-countdown {
from { width: 100%; }
to { width: 0; }
}
.notification-enter {
@apply transform ease-out duration-300 transition;
}
.notification-enter-from {
@apply translate-y-2 opacity-0;
}
.notification-enter-to {
@apply translate-y-0 opacity-100;
}
@screen sm {
.notification-enter-from {
@apply translate-y-0 translate-x-2;
}
.notification-enter-to {
@apply translate-x-0;
}
}
.notification-leave {
@apply transition ease-in duration-100;
}
.notification-leave-from {
@apply opacity-100;
}
.notification-leave-to {
@apply opacity-0;
}
}

View File

@@ -0,0 +1,45 @@
@layer components {
.pagy-nav.pagination {
@apply isolate inline-flex -space-x-px rounded-md shadow-sm;
}
.pagy-nav .page:not(.prev):not(.next) {
@apply hidden sm:inline-block;
}
.pagy-nav .page.next a {
@apply relative inline-flex items-center rounded-r-md border
border-gray-300 bg-white px-3 py-2 text-sm font-medium
text-gray-500 hover:bg-gray-100 focus:z-20;
}
.pagy-nav .page.prev a {
@apply relative inline-flex items-center rounded-l-md border
border-gray-300 bg-white px-3 py-2 text-sm font-medium
text-gray-500 hover:bg-gray-100 focus:z-20;
}
.pagy-nav .page.next.disabled {
@apply relative inline-flex items-center rounded-r-md border
border-gray-300 bg-gray-100 px-3 py-2 text-sm font-medium
text-gray-400 focus:z-20;
}
.pagy-nav .page.prev.disabled {
@apply relative inline-flex items-center rounded-l-md border
border-gray-300 bg-gray-100 px-3 py-2 text-sm font-medium
text-gray-400 focus:z-20;
}
.pagy-nav .page a, .page.gap {
@apply bg-white border-gray-300 text-gray-500 hover:bg-gray-100 relative
inline-flex items-center border px-4 py-2 text-sm font-medium
focus:z-20;
}
.pagy-nav .page.active {
@apply z-10 border-indigo-500 bg-indigo-50 text-indigo-600 relative
inline-flex items-center border px-4 py-2 text-sm font-medium
focus:z-20;
}
}

View File

@@ -0,0 +1,36 @@
@layer components {
table {
@apply w-full;
}
table thead tr {
@apply text-left;
}
table thead th {
@apply pb-3.5 text-sm font-normal uppercase text-gray-500;
}
table tbody th {
@apply text-left font-normal text-gray-500;
}
table th:not(:last-of-type),
table td:not(:last-of-type) {
@apply pr-2;
}
table td, tbody th {
@apply py-2;
}
table.divided {
@apply divide-y divide-gray-300;
}
table.divided tbody {
@apply divide-y divide-gray-200;
}
table.divided td, table.divided tbody th {
@apply py-3;
}
}

View File

@@ -1,20 +0,0 @@
@font-face {
font-family: 'Raleway';
src: url('/fonts/raleway-light.woff') format('woff2');
font-weight: 300;
font-style: normal;
}
body {
font-family: "Open Sans", Helvetica, Arial, sans-serif;
font-weight: 400;
}
h1, h2, h3 {
font-family: Raleway, inherit;
font-weight: 300;
}
h1 {
text-transform: uppercase;
}

View File

@@ -1,146 +0,0 @@
$content-width: 800px;
$content-max-width: 100%;
body {
}
#wrapper {
width: 100%;
text-align: center;
> header {
margin: 0 auto;
padding: 4rem 0;
text-align: center;
background: #0d4f99;
background: linear-gradient(35deg, #8955a0 0, #0d4f99 100%);
h1 {
font-size: 1.8rem;
color: #fff;
span.project-name {
display: none;
// font-size: .5em;
// text-transform: none;
// vertical-align: super;
}
span.beta {
font-size: .5em;
font-style: italic;
text-transform: none;
vertical-align: super;
}
span.bolt {
color: #ffd000;
}
}
p.current-user {
margin-top: 2rem;
color: rgba(255,255,255,0.6);
strong {
font-weight: 400;
color: #fff;
// color: #ffd000;
// color: #ccff40;
}
}
a {
color: rgba(255,255,255,0.6);
transition: color 0.1s linear;
&:hover, &:active {
color: #fff;
}
}
}
}
.flash-msg {
width: 100%;
text-align: center;
padding: 2rem 0;
&.notice {
background: #efffc4;
}
&.alert {
background: #fff4c2;
}
}
main {
width: $content-width;
max-width: $content-max-width;
margin: 4rem auto;
text-align: left;
h2, h3 {
margin-bottom: 1.5em;
}
h2 {
font-size: 1.5rem;
}
h3 {
font-size: 1.25rem;
}
p {
line-height: 1.5rem;
margin-bottom: 1rem;
&.notice {
text-align: center;
}
}
ul {
margin-bottom: 1.5rem;
li {
line-height: 1.5rem;
}
}
th, td {
line-height: 1.5rem;
padding-right: 1rem;
}
section {
border-bottom: 1px dotted #ccc;
padding-bottom: 4rem;
margin-bottom: 4rem;
}
}
.grid {
display: grid;
&.services {
grid-template-columns: 1fr 1fr 1fr;
grid-row-gap: 1rem;
grid-column-gap: 2rem;
margin-top: 3rem;
h3 {
margin-bottom: 1rem;
}
.grid-item {
p {
color: #888;
font-size: 0.85rem;
}
}
}
}

View File

@@ -0,0 +1,15 @@
<div class="flex">
<div class="<%= @icon_container_class %>">
<%= image_tag(@icon_path, class: 'h-full w-full') %>
</div>
<div class="flex-1 px-4">
<h4 class="sm:pt-2 mb-2 text-lg font-bold"><%= @name %></h4>
<p class="leading-snug"><%= @description %></p>
<p class="leading-snug flex flex-wrap gap-3">
<% @links.each do |link| %>
<a href="<%= link[1] %>" target="_blank"
class="flex-0 btn-sm btn-gray"><%= link[0] %></a>
<% end %>
</p>
</div>
</div>

View File

@@ -0,0 +1,19 @@
# frozen_string_literal: true
class AppInfoComponent < ViewComponent::Base
def initialize(name:, description:, icon_path: , icon_fill_box: false, links: [])
@name = name
@description = description
@icon_path = icon_path
@icon_container_class = icon_container_class(icon_fill_box)
@links = links
end
def icon_container_class(icon_fill_box)
str = "flex-0 h-16 w-16 sm:h-28 sm:w-28 bg-white rounded-3xl overflow-hidden"
unless icon_fill_box
str += " p-2 border border-gray-200"
end
str
end
end

View File

@@ -0,0 +1,45 @@
<%= tag.public_send(@tag, class: "mb-6 last:mb-0", data: {
:'field-name' => @field_name
}) do %>
<% if @positioning == :vertical %>
<label class="block">
<p class="font-bold <%= @descripton.present? ? "mb-1" : "mb-2" %>">
<%= @title %>
</p>
<% if @descripton.present? %>
<p class="text-gray-500">
<%= @descripton %>
</p>
<% end %>
<%= tag.p class: "flex gap-x-1", data: {
controller: @resettable ? "settings--resettable-field" : nil,
} do %>
<%= content %>
<% if @resettable %>
<button type="button"
class="relative grow-0 shrink-0 btn-md btn-outline text-red-700"
title="Reset to default value"
data-settings--resettable-field-target="resetButton"
data-action="settings--resettable-field#resetField">
Reset
</button>
<% end %>
<% end %>
</label>
<% elsif @positioning == :horizontal %>
<label class="block flex items-center justify-between">
<div class="flex flex-col">
<label class="font-bold mb-1"><%= @title %></label>
<% if @descripton.present? %>
<p class="text-gray-500"><%= @descripton %></p>
<% end %>
</div>
<div class="relative ml-4 inline-flex flex-shrink-0">
<%= content %>
</div>
</label>
<% else %>
<p>Invalid <code>positioning<code> argument for <code>FieldsetComponent</code>.</p>
<% end %>
<% end %>

View File

@@ -0,0 +1,16 @@
# frozen_string_literal: true
module FormElements
class FieldsetComponent < ViewComponent::Base
def initialize(tag: "li", positioning: :vertical,
title:, description: nil,
field_name: nil, resettable: false)
@tag = tag
@positioning = positioning
@title = title
@descripton = description
@field_name = field_name
@resettable = resettable
end
end
end

View File

@@ -0,0 +1,13 @@
<%= render FormElements::FieldsetComponent.new(
title: @title,
description: @description,
field_name: "setting_#{@key.to_s}",
resettable: @resettable
) do %>
<%= method("#{@type}_field").call :setting, @key,
value: Setting.public_send(@key),
data: {
:'default-value' => Setting.get_field(@key)[:default]
},
class: "w-full" %>
<% end %>

View File

@@ -0,0 +1,20 @@
# frozen_string_literal: true
module FormElements
class FieldsetResettableSettingComponent < ViewComponent::Base
def initialize(tag: "li", key:, type: :text, title:, description: nil)
@tag = tag
@positioning = :vertical
@title = title
@descripton = description
@key = key.to_sym
@type = type
@resettable = is_resettable?(@key)
end
def is_resettable?(key)
default_value = Setting.get_field(key)[:default]
default_value.present? && (default_value != Setting.send(key))
end
end
end

View File

@@ -0,0 +1,33 @@
<%= tag.public_send @tag, class: "flex items-center justify-between mb-6 last:mb-0",
data: @form_enabled ? {
controller: "settings--toggle",
:'settings--toggle-switch-enabled-value' => @enabled.to_s
} : nil do %>
<div class="flex flex-col">
<label class="font-bold mb-1"><%= @title %></label>
<p class="text-gray-500"><%= @descripton %></p>
</div>
<div class="relative ml-4 inline-flex flex-shrink-0">
<%= render FormElements::ToggleComponent.new(
enabled: @enabled,
input_enabled: @input_enabled,
class_names: @form_enabled ? "hidden" : nil,
data: {
:'settings--toggle-target' => "button",
action: "settings--toggle#toggleSwitch"
}) %>
<% if @form_enabled %>
<% if @attribute.present? %>
<%= @form.check_box @attribute, {
checked: @enabled,
data: { :'settings--toggle-target' => "checkbox" }
}, "true", "false" %>
<% else %>
<input name="<%= @field_name %>" type="hidden" value="false" autocomplete="off">
<%= check_box_tag @field_name, "true", @enabled, {
data: { :'settings--toggle-target' => "checkbox" }
} %>
<% end %>
<% end %>
</div>
<% end %>

View File

@@ -0,0 +1,19 @@
# frozen_string_literal: true
module FormElements
class FieldsetToggleComponent < ViewComponent::Base
def initialize(tag: "li", form: nil, attribute: nil, field_name: nil,
enabled: false, input_enabled: true, title:, description:)
@tag = tag
@form = form
@attribute = attribute
@field_name = field_name
@form_enabled = @form.present? || @field_name.present?
@enabled = enabled
@input_enabled = input_enabled
@title = title
@descripton = description
@button_text = @enabled ? "Switch off" : "Switch on"
end
end
end

View File

@@ -0,0 +1,15 @@
<%= button_tag type: "button", name: "toggle", data: @data,
role: "switch", aria: { checked: @enabled.to_s },
tabindex: @tabindex, disabled: !@input_enabled,
class: "#{ @enabled ? 'bg-blue-600' : 'bg-gray-200' }
#{ @class_names.present? ? @class_names : '' }
relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer
rounded-full border-2 border-transparent transition-colors
duration-200 ease-in-out focus:outline-none focus:ring-2
focus:ring-blue-600 focus:ring-offset-2" do %>
<span class="sr-only"><%= @button_text %></span>
<span aria-hidden="true" data-settings--toggle-target="switch"
class="<%= @enabled ? 'translate-x-5' : 'translate-x-0' %>
pointer-events-none inline-block h-5 w-5 transform rounded-full
bg-white shadow ring-0 transition duration-200 ease-in-out"></span>
<% end %>

View File

@@ -0,0 +1,13 @@
# frozen_string_literal: true
module FormElements
class ToggleComponent < ViewComponent::Base
def initialize(enabled:, input_enabled: true, data: nil, class_names: nil, tabindex: nil)
@enabled = !!enabled
@input_enabled = input_enabled
@data = data
@class_names = class_names
@tabindex = tabindex
end
end
end

View File

@@ -0,0 +1,7 @@
<header class="py-10">
<div class="max-w-xl mx-auto px-4 sm:px-6 lg:px-8">
<h1 class="text-3xl font-bold text-white text-center">
<%= @title %>
</h1>
</div>
</header>

View File

@@ -0,0 +1,7 @@
# frozen_string_literal: true
class HeaderCompactComponent < ViewComponent::Base
def initialize(title:)
@title = title
end
end

View File

@@ -0,0 +1,7 @@
<header class="py-10">
<div class="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
<h1 class="text-3xl font-bold text-white">
<%= @title %>
</h1>
</div>
</header>

View File

@@ -0,0 +1,7 @@
# frozen_string_literal: true
class HeaderComponent < ViewComponent::Base
def initialize(title:)
@title = title
end
end

View File

@@ -0,0 +1,5 @@
<main class="w-full max-w-xl mx-auto pb-12 px-4 sm:px-6 lg:px-8">
<div class="bg-white rounded-lg shadow px-6 sm:px-12 py-8 sm:py-12">
<%= content %>
</div>
</main>

View File

@@ -0,0 +1,5 @@
# frozen_string_literal: true
class MainCompactComponent < ViewComponent::Base
end

View File

@@ -0,0 +1,5 @@
<main class="w-full max-w-6xl mx-auto pb-12 px-4 md:px-6 lg:px-8">
<div class="md:min-h-[50vh] bg-white rounded-lg shadow px-6 sm:px-12 py-8 sm:py-12">
<%= content %>
</div>
</main>

View File

@@ -0,0 +1,5 @@
# frozen_string_literal: true
class MainSimpleComponent < ViewComponent::Base
end

View File

@@ -0,0 +1,15 @@
<main class="w-full max-w-6xl mx-auto pb-12 px-4 md:px-6 lg:px-8">
<div class="bg-white rounded-lg shadow">
<div class="md:min-h-[50vh] divide-y divide-gray-200 lg:grid lg:grid-cols-12 lg:divide-y-0 lg:divide-x">
<aside class="py-6 sm:py-8 lg:col-span-3">
<nav class="space-y-1">
<%= render partial: @sidenav_partial %>
</nav>
</aside>
<div class="lg:col-span-9 px-6 sm:px-12 py-8 sm:pt-10 sm:pb-12">
<%= content %>
</div>
</div>
</div>
</main>

View File

@@ -0,0 +1,7 @@
# frozen_string_literal: true
class MainWithSidenavComponent < ViewComponent::Base
def initialize(sidenav_partial:)
@sidenav_partial = sidenav_partial
end
end

View File

@@ -0,0 +1,10 @@
<main class="w-full max-w-6xl mx-auto pb-12 px-4 md:px-6 lg:px-8">
<div class="bg-white rounded-lg shadow">
<div class="px-6 sm:px-12 pt-2 sm:pt-4">
<%= render partial: @tabnav_partial %>
</div>
<div class="px-6 sm:px-12 py-8 sm:py-12">
<%= content %>
</div>
</div>
</main>

View File

@@ -0,0 +1,7 @@
# frozen_string_literal: true
class MainWithTabnavComponent < ViewComponent::Base
def initialize(tabnav_partial:)
@tabnav_partial = tabnav_partial
end
end

View File

@@ -0,0 +1,28 @@
<div tabindex="-1" class="relative z-10">
<!-- Modal Background -->
<div class="hidden fixed inset-0 bg-black bg-opacity-80 overflow-y-auto flex items-center justify-center"
data-modal-target="background"
data-action="click->modal#closeBackground"
data-transition-enter="transition-all ease-in-out duration-100"
data-transition-enter-from="bg-opacity-0"
data-transition-enter-to="bg-opacity-80"
data-transition-leave="transition-all ease-in-out duration-100"
data-transition-leave-from="bg-opacity-80"
data-transition-leave-to="bg-opacity-0">
<!-- Modal Container -->
<div data-modal-target="container"
class="max-h-screen w-auto max-w-lg relative
hidden animate-scale-in fixed inset-0 overflow-y-auto flex items-center justify-center">
<!-- Modal Card -->
<div class="m-1 bg-white rounded shadow">
<div class="p-8">
<%= content %>
<div class="flex justify-end items-center flex-wrap mt-6">
<button class="btn-md btn-blue" data-action="click->modal#close:prevent">Close</button>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,2 @@
class ModalComponent < ViewComponent::Base
end

View File

@@ -0,0 +1,49 @@
<div class="flash-msg <%= @type %> hidden max-w-sm w-full bg-white shadow-lg rounded-lg pointer-events-auto mt-4"
data-turbo="false"
data-notification-action-url="<%= @data.dig(:action, :url) %>"
data-notification-action-method="<%= @data.dig(:action, :method) %>"
data-notification-timeout="<%= @data[:timeout] %>"
data-controller="notification">
<div class="rounded-lg shadow-xs overflow-hidden">
<div class="p-4">
<div class="flex items-start">
<div class="flex-shrink-0">
<span class="inline-block h-6 w-6 <%= @icon_color_class %>">
<%= render "icons/#{@icon_name}" %>
</span>
</div>
<div class="ml-3 w-0 flex-1 pt-0.5">
<p class="text-sm leading-5 font-medium text-gray-900">
<%= @data[:title] %>
</p>
<% if @data[:body].present? %>
<p class="mt-1 text-sm leading-5 text-gray-500">
<%= @data[:body] %>
</p>
<% end %>
<% if @data[:action].present? %>
<div class="mt-2" data-notification-target="buttons">
<a data-turbo-frame="_top" <% if @data.dig(:action, :method) == 'get' %> href="<%= @data.dig(:action, :url) %>" <% else %> href="#" data-action="notification#run" <% end %> class="text-sm leading-5 font-medium text-indigo-600 hover:text-indigo-500 focus:outline-none focus:underline transition ease-in-out duration-150">
<%= @data.dig(:action, :name) %>
</a>
<button data-action="notification#close" class="ml-6 text-sm leading-5 font-medium text-gray-700 hover:text-gray-500 focus:outline-none focus:underline transition ease-in-out duration-150">
<%= t('.dismiss') %>
</button>
</div>
<% end %>
</div>
<div class="ml-4 flex-shrink-0 flex">
<button class="inline-flex text-gray-400 focus:outline-none focus:text-gray-500 transition ease-in-out duration-150" data-action="notification#close">
<!-- Heroicon name: solid/x -->
<svg class="h-5 w-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd" />
</svg>
</button>
</div>
</div>
</div>
<% if @data[:countdown] %>
<div class="bg-indigo-600 rounded-lg h-1 w-0" data-notification-target="countdown"></div>
<% end %>
</div>
</div>

View File

@@ -0,0 +1,54 @@
# frozen_string_literal: true
# @param type [String] Classic notification type `error`, `alert` and `info` + custom `success`
# @param data [String, Hash] `String` for backward compatibility,
# `Hash` for the new functionality `{title: '', body: '', timeout: 5, countdown: false, action: { url: '', method: '', name: ''}}`.
# The `title` attribute for `Hash` is mandatory.
class NotificationComponent < ViewComponent::Base
def initialize(type:, data:)
@type = type
@data = prepare_data(data)
@icon_name = icon_name
@icon_color_class = icon_color_class
@data[:timeout] ||= 5
@data[:action][:method] ||= "get" if @data[:action]
end
private
def prepare_data(data)
case data
when Hash
data
else
{ title: data }
end
end
def icon_name
case @type
when 'success'
'check-circle'
when 'error'
'alert-octagon'
when 'alert'
'alert-octagon'
else
'info'
end
end
def icon_color_class
case @type
when 'success'
'text-emerald-500'
when 'error'
'text-rose-600'
when 'alert'
'text-rose-600'
else
'text-gray-400'
end
end
end

View File

@@ -0,0 +1,6 @@
<%= render ModalComponent.new do %>
<% if @descripton.present? %>
<p class="mb-6"><%= @description %></p>
<% end %>
<p><%= raw @qr_code_svg %></p>
<% end %>

View File

@@ -0,0 +1,24 @@
require "rqrcode"
class QrCodeModalComponent < ViewComponent::Base
def initialize(qr_content:, description: nil)
@description = description
@qr_code_svg = qr_code_svg(qr_content)
end
private
def qr_code_svg(content)
qr_code = RQRCode::QRCode.new(content)
qr_code.as_svg(
color: "000",
shape_rendering: "crispEdges",
module_size: 6,
standalone: true,
use_path: true,
svg_attributes: {
class: 'inline-block'
}
)
end
end

View File

@@ -0,0 +1,3 @@
<dl class="grid grid-cols-2 lg:grid-cols-4 gap-6 sm:gap-12">
<%= content %>
</dl>

View File

@@ -0,0 +1,4 @@
# frozen_string_literal: true
class QuickstatsContainerComponent < ViewComponent::Base
end

View File

@@ -0,0 +1,18 @@
<div class="">
<dt class="mb-2 text-gray-500">
<%= @title %>
</dt>
<dd>
<% if @type == :number %>
<span class="text-2xl"><%= number_with_delimiter @value %></span>
<% else %>
<span class="text-2xl"><%= @value %></span>
<% end %>
<% if @unit %>
<span><%= @unit %></span>
<% end %>
<% if @meta %>
<span class="text-gray-500"><%= @meta %></span>
<% end %>
</dd>
</div>

View File

@@ -0,0 +1,13 @@
# frozen_string_literal: true
class QuickstatsItemComponent < ViewComponent::Base
def initialize(type:, title:, value:, unit: nil, meta: nil, icon_name: nil, icon_color_class: nil)
@type = type
@title = title
@value = value
@unit = unit
@meta = meta
@icon_name = icon_name
@icon_color_class = icon_color_class
end
end

View File

@@ -0,0 +1,4 @@
<%= link_to @path, class: @link_class, title: (@disabled ? "Coming soon" : nil) do %>
<%= render partial: "icons/#{@icon}", locals: { custom_class: @icon_class } %>
<span class="truncate"><%= @name %></span>
<% end %>

View File

@@ -0,0 +1,37 @@
# frozen_string_literal: true
class SidenavLinkComponent < ViewComponent::Base
def initialize(name:, level: 1, path:, icon:, active: false, disabled: false)
@name = name
@level = level
@path = path
@icon = icon
@active = active
@disabled = disabled
@link_class = class_names_link(path)
@icon_class = class_names_icon(path)
end
def class_names_link(path)
px = @level == 1 ? "px-4" : "pl-8 pr-4"
base = "#{px} py-2 group border-l-4 flex items-center text-base font-medium"
if @active
"#{base} bg-teal-50 border-teal-500 text-teal-700 hover:bg-teal-50 hover:text-teal-700"
elsif @disabled
"#{base} border-transparent text-gray-400 hover:bg-gray-50"
else
"#{base} border-transparent text-gray-900 hover:bg-gray-50 hover:text-gray-900"
end
end
def class_names_icon(path)
if @active
"text-teal-500 group-hover:text-teal-500 flex-shrink-0 -ml-1 mr-3 h-6 w-6"
elsif @disabled
"text-gray-300 group-hover:text-gray-300 flex-shrink-0 -ml-1 mr-3 h-6 w-6"
else
"text-gray-400 group-hover:text-gray-500 flex-shrink-0 -ml-1 mr-3 h-6 w-6"
end
end
end

View File

@@ -0,0 +1,3 @@
<%= link_to @path, class: @link_class do %>
<%= @name %>
<% end %>

View File

@@ -0,0 +1,21 @@
# frozen_string_literal: true
class TabnavLinkComponent < ViewComponent::Base
def initialize(name:, path:, active: false, disabled: false)
@name = name
@path = path
@active = active
@disabled = disabled
@link_class = class_names_link(path)
end
def class_names_link(path)
if @active
"border-indigo-500 text-indigo-600 w-1/2 py-4 px-1 text-center border-b-2"
elsif @disabled
"border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 w-1/2 py-4 px-1 text-center border-b-2"
else
"border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 w-1/2 py-4 px-1 text-center border-b-2"
end
end
end

View File

@@ -0,0 +1,22 @@
<section class="w-full grid grid-cols-1 md:grid-cols-12 md:mb-0">
<div class="md:col-span-8">
<p>
Send and receive sats via the Bitcoin Lightning Network.
</p>
</div>
<div class="md:col-span-4 mt-4 md:mt-0">
<p class="font-mono md:text-right mb-0 p-4 border border-gray-300 rounded-lg overflow-hidden">
<% if @balance %>
<span class="text-2xl"><%= number_with_delimiter @balance %></span>
<span class="text-xl">sats</span>
<br>
<span class="text-sm text-gray-500">Available balance</span>
<% else %>
<span class="text-2xl">n/a</span>
<span class="text-xl">sats</span>
<br>
<span class="text-sm text-gray-500">Balance unavailable</span>
<% end %>
</p>
</div>
</section>

View File

@@ -0,0 +1,8 @@
# frozen_string_literal: true
class WalletSummaryComponent < ViewComponent::Base
def initialize(balance:)
@balance = balance
end
end

View File

@@ -0,0 +1,7 @@
class AccountController < ApplicationController
before_action :authenticate_user!
def index
@current_section = :account
end
end

View File

@@ -1,6 +1,11 @@
class Admin::BaseController < ApplicationController
include Pagy::Backend
before_action :authenticate_user!
before_action :authorize_admin
before_action :set_context
def set_context
@context = :admin
end
end

View File

@@ -1,4 +1,5 @@
class Admin::DashboardController < Admin::BaseController
def index
@current_section = :dashboard
end
end

View File

@@ -0,0 +1,95 @@
class Admin::DonationsController < Admin::BaseController
before_action :set_donation, only: [:show, :edit, :update, :destroy]
before_action :set_current_section, only: [:index, :show, :new, :edit]
# GET /donations
# GET /donations.json
def index
@pagy, @donations = pagy(Donation.all.order('created_at desc'))
@stats = {
overall_sats: @donations.all.sum("amount_sats"),
donor_count: Donation.distinct.count(:user_id)
}
end
# GET /donations/1
# GET /donations/1.json
def show
end
# GET /donations/new
def new
@donation = Donation.new
end
# GET /donations/1/edit
def edit
end
# POST /donations
# POST /donations.json
def create
@donation = Donation.new(donation_params)
respond_to do |format|
if @donation.save
format.html do
redirect_to admin_donation_url(@donation), flash: {
success: 'Donation was successfully created.'
}
end
format.json { render :show, status: :created, location: @donation }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @donation.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /donations/1
# PATCH/PUT /donations/1.json
def update
respond_to do |format|
if @donation.update(donation_params)
format.html do
redirect_to admin_donation_url(@donation), flash: {
success: 'Donation was successfully updated.'
}
end
format.json { render :show, status: :ok, location: @donation }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: @donation.errors, status: :unprocessable_entity }
end
end
end
# DELETE /donations/1
# DELETE /donations/1.json
def destroy
@donation.destroy
respond_to do |format|
format.html do redirect_to admin_donations_url, flash: {
success: 'Donation was successfully destroyed.'
}
end
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_donation
@donation = Donation.find(params[:id])
end
# Only allow a list of trusted parameters through.
def donation_params
params.require(:donation).permit(:user_id, :amount_sats, :amount_eur, :amount_usd, :public_name, :paid_at)
end
def set_current_section
@current_section = :donations
end
end

View File

@@ -0,0 +1,12 @@
class Admin::InvitationsController < Admin::BaseController
def index
@current_section = :invitations
@pagy, @invitations_used = pagy(Invitation.used.order('used_at desc'))
@stats = {
available: Invitation.unused.count,
accepted: @invitations_used.length,
users_with_referrals: Invitation.used.distinct.count(:user_id)
}
end
end

View File

@@ -1,41 +0,0 @@
class Admin::LdapUsersController < Admin::BaseController
def index
attributes = %w{dn cn uid mail admin}
filter = Net::LDAP::Filter.eq("uid", "*")
if params[:ou]
treebase = "ou=#{params[:ou]},cn=users,dc=kosmos,dc=org"
else
treebase = "ou=kosmos.org,cn=users,dc=kosmos,dc=org"
end
entries = ldap_client.search(base: treebase, filter: filter, attributes: attributes)
entries.sort_by! { |e| e.cn[0] }
@entries = entries.collect do |e|
{
uid: e.uid.first,
mail: e.try(:mail) ? e.mail.first : nil,
admin: e.try(:admin) ? 'admin' : nil
# password: e.userpassword.first
}
end
# ldap_client.get_operation_result
end
private
def ldap_client
ldap_client ||= Net::LDAP.new host: ENV['LDAP_HOST'],
port: ldap_config['port'],
encryption: ldap_config['ssl'],
auth: {
method: :simple,
username: ldap_config['admin_user'],
password: ldap_config['admin_password']
}
end
def ldap_config
ldap_config ||= YAML.load(ERB.new(File.read("#{Rails.root}/config/ldap.yml")).result)[Rails.env]
end
end

View File

@@ -0,0 +1,21 @@
class Admin::LightningController < Admin::BaseController
before_action :check_feature_enabled
def index
@current_section = :lightning
@users = User.pluck(:cn, :ou, :ln_account)
@accounts = LndhubAccount.with_balances.order(balance: :desc).to_a
@ln = {}
@ln[:current_balance] = LndhubAccount.current.joins(:ledgers).sum("account_ledgers.amount")
@ln[:users_with_sats] = @accounts.length
end
def check_feature_enabled
if !Setting.lndhub_admin_enabled?
flash[:alert] = "Lightning Admin UI not enabled"
redirect_to admin_root_path and return
end
end
end

View File

@@ -0,0 +1,12 @@
class Admin::Settings::RegistrationsController < Admin::SettingsController
def index
end
def create
update_settings
redirect_to admin_settings_registrations_path, flash: {
success: "Settings saved"
}
end
end

View File

@@ -0,0 +1,19 @@
class Admin::Settings::ServicesController < Admin::SettingsController
def index
@service = params[:s]
if @service.blank?
redirect_to admin_settings_services_path(params: { s: "discourse" })
end
end
def create
service = params.require(:service)
update_settings
redirect_to admin_settings_services_path(params: { s: service }), flash: {
success: "Settings saved"
}
end
end

View File

@@ -0,0 +1,40 @@
class Admin::SettingsController < Admin::BaseController
before_action :set_current_section
def index
end
def update_settings
@errors = ActiveModel::Errors.new(Setting.new)
changed_keys = []
setting_params.keys.each do |key|
next if setting_params[key].nil? ||
(Setting.send(key).to_s == setting_params[key].strip)
changed_keys.push(key)
setting = Setting.new(var: key)
setting.value = setting_params[key].strip
unless setting.valid?
@errors.merge!(setting.errors)
end
end
if @errors.any?
render :index and return
end
changed_keys.each do |key|
Setting.send("#{key}=", setting_params[key].strip)
end
end
private
def set_current_section
@current_section = :settings
end
def setting_params
params.require(:setting).permit(Setting.editable_keys.map(&:to_sym))
end
end

View File

@@ -0,0 +1,35 @@
class Admin::UsersController < Admin::BaseController
before_action :set_user, only: [:show]
before_action :set_current_section
def index
ldap = LdapService.new
@ou = params[:ou] || Setting.primary_domain
@orgs = ldap.fetch_organizations
@pagy, @users = pagy(User.where(ou: @ou).order(cn: :asc))
@stats = {
users_confirmed: User.where(ou: @ou).confirmed.count,
users_pending: User.where(ou: @ou).pending.count
}
end
def show
if Setting.lndhub_admin_enabled?
@lndhub_user = @user.lndhub_user
end
@services_enabled = @user.services_enabled
end
private
def set_user
address = params[:address].split("@")
@user = User.where(cn: address.first, ou: address.last).first
end
def set_current_section
@current_section = :users
end
end

View File

@@ -0,0 +1,5 @@
class Api::BaseController < ApplicationController
layout false
end

View File

@@ -0,0 +1,13 @@
class Api::KreditsController < Api::BaseController
def onchain_btc_balance
btcpay = BtcPay.new
balance = btcpay.onchain_wallet_balance
render json: balance
rescue => error
Rails.logger.warn "Failed to fetch kredits BTC wallet balance: #{error.message}"
render json: { error: 'Failed to fetch wallet balance' },
status: 500
end
end

View File

@@ -3,12 +3,30 @@ class ApplicationController < ActionController::Base
render :text => exception, :status => 500
end
before_action :sentry_set_user
def sentry_set_user
return unless Setting.sentry_enabled
if user_signed_in?
Sentry.set_user(id: current_user.id, username: current_user.cn)
else
Sentry.set_user({})
end
end
def require_user_signed_in
unless user_signed_in?
redirect_to welcome_path and return
end
end
def require_user_signed_out
if user_signed_in?
redirect_to root_path and return
end
end
def authorize_admin
http_status :forbidden unless current_user.is_admin?
end

View File

@@ -0,0 +1,10 @@
class Contributions::DonationsController < ApplicationController
before_action :authenticate_user!
# GET /donations
# GET /donations.json
def index
@donations = current_user.donations.completed
@current_section = :contributions
end
end

View File

@@ -0,0 +1,8 @@
class Contributions::ProjectsController < ApplicationController
before_action :authenticate_user!
# GET /contributions
def index
@current_section = :contributions
end
end

View File

@@ -2,5 +2,6 @@ class DashboardController < ApplicationController
before_action :require_user_signed_in
def index
@current_section = :services
end
end

View File

@@ -0,0 +1,17 @@
class Discourse::SsoController < ApplicationController
before_action :authenticate_user!
def connect
secret = Setting.discourse_connect_secret
sso = DiscourseApi::SingleSignOn.parse(request.query_string, secret)
sso.external_id = current_user.id
sso.email = current_user.email
sso.username = current_user.cn
sso.name = current_user.display_name
sso.admin = current_user.is_admin?
sso.sso_secret = secret
redirect_to sso.to_url("#{Setting.discourse_public_url}/session/sso_login"),
allow_other_host: true
end
end

View File

@@ -0,0 +1,51 @@
class InvitationsController < ApplicationController
before_action :authenticate_user!, except: ["show"]
before_action :require_user_signed_out, only: ["show"]
# GET /invitations
def index
@invitations_unused = current_user.invitations.unused
@invitations_used = current_user.invitations.used.order('used_at desc')
@current_section = :invitations
end
# GET /invitations/a-random-invitation-token
def show
token = session[:invitation_token] = params[:id]
if Invitation.where(token: token, used_at: nil).exists?
redirect_to signup_path and return
else
flash.now[:alert] = "This invitation either doesn't exist or has already been used."
http_status :unauthorized
end
end
# POST /invitations
def create
@invitation = Invitation.new(user: current_user)
respond_to do |format|
if @invitation.save
format.html do redirect_to @invitation, flash: {
success: 'Invitation was successfully created.'
}
end
format.json { render :show, status: :created, location: @invitation }
else
format.html { render :new }
format.json { render json: @invitation.errors, status: :unprocessable_entity }
end
end
end
# DELETE /invitations/1
def destroy
@invitation = current_user.invitations.find(params[:id])
@invitation.destroy
respond_to do |format|
format.html { redirect_to invitations_url }
format.json { head :no_content }
end
end
end

View File

@@ -0,0 +1,95 @@
class LnurlpayController < ApplicationController
before_action :check_feature_enabled
before_action :find_user_by_address
MIN_SATS = 10
MAX_SATS = 1_000_000
MAX_COMMENT_CHARS = 100
def index
render json: {
status: "OK",
callback: "https://accounts.kosmos.org/lnurlpay/#{@user.address}/invoice",
tag: "payRequest",
maxSendable: MAX_SATS * 1000, # msat
minSendable: MIN_SATS * 1000, # msat
metadata: metadata(@user.address),
commentAllowed: MAX_COMMENT_CHARS
}
end
def keysend
http_status :not_found and return unless Setting.lndhub_keysend_enabled?
render json: {
status: "OK",
tag: "keysend",
pubkey: Setting.lndhub_public_key,
customData: [{
customKey: "696969",
customValue: @user.ln_account
}]
}
end
def invoice
amount = params[:amount].to_i / 1000 # msats
address = params[:address]
comment = params[:comment] || ""
if !valid_amount?(amount)
render json: { status: "ERROR", reason: "Invalid amount" }
return
end
if !valid_comment?(comment)
render json: { status: "ERROR", reason: "Comment too long" }
return
end
memo = "To #{address}"
memo = "#{memo}: \"#{comment}\"" if comment.present?
payment_request = @user.ln_create_invoice({
amount: amount, # we create invoices in sats
memo: memo,
description_hash: Digest::SHA2.hexdigest(metadata(address)),
})
render json: {
status: "OK",
successAction: {
tag: "message",
message: "Sats received. Thank you!"
},
routes: [],
pr: payment_request
}
end
private
def find_user_by_address
address = params[:address].split("@")
@user = User.where(cn: address.first, ou: address.last).first
http_status :not_found if @user.nil?
end
def metadata(address)
"[[\"text/identifier\", \"#{address}\"], [\"text/plain\", \"Send sats, receive thanks.\"]]"
end
def valid_amount?(amount_in_sats)
amount_in_sats <= MAX_SATS && amount_in_sats >= MIN_SATS
end
def valid_comment?(comment)
comment.length <= MAX_COMMENT_CHARS
end
private
def check_feature_enabled
http_status :not_found unless Setting.lndhub_enabled?
end
end

View File

@@ -0,0 +1,145 @@
class Rs::OauthController < ApplicationController
before_action :require_signed_in_with_username, only: :new
before_action :authenticate_user!, only: :create
def new
username, org = params[:useraddress].split("@")
@user = User.where(cn: username.downcase, ou: org).first
@scopes = parse_scopes params[:scope]
@redirect_uri = params[:redirect_uri]
@client_id = params[:client_id]
@state = params[:state]
@root_access_requested = (@scopes & [":r",":rw"]).any?
@denial_url = url_with_state("#{@redirect_uri}#error=access_denied", @state)
@expire_at_dates = [["Never", nil],
["In 1 month", 1.month.from_now],
["In 1 day", 1.day.from_now]]
http_status :bad_request and return unless @redirect_uri.present?
unless current_user == @user
sign_out :user
redirect_to new_rs_oauth_url(@user.address,
scope: params[:scope],
redirect_uri: params[:redirect_uri],
client_id: params[:client_id],
state: params[:state])
return
end
unless @client_id.present?
redirect_to(url_with_state("#{@redirect_uri}#error=invalid_request", @state),
allow_other_host: true) and return
end
if @scopes.empty?
redirect_to(url_with_state("#{@redirect_uri}#error=invalid_scope", @state),
allow_other_host: true) and return
end
unless hostname_of(@client_id) == hostname_of(@redirect_uri)
redirect_to(url_with_state("#{@redirect_uri}#error=invalid_client", @state),
allow_other_host: true) and return
end
@client_id.gsub!(/http(s)?:\/\//, "")
if auth = current_user.remote_storage_authorizations.valid.where(permissions: @scopes, client_id: @client_id).first
redirect_to(url_with_state("#{@redirect_uri}#access_token=#{auth.token}", @state),
allow_other_host: true) and return
end
end
def create
unless current_user.id.to_s == params[:user_id]
Rails.logger.info("NO MATCH: #{params[:user_id]}, #{current_user.id}")
http_status :forbidden and return
end
permissions = parse_scopes params[:scope]
redirect_uri = params[:redirect_uri].presence
client_id = params[:client_id].presence
state = params[:state].presence
expire_at = params[:expire_at].presence
http_status :bad_request and return unless redirect_uri.present?
if permissions.empty?
redirect_to(url_with_state("#{redirect_uri}#error=invalid_scope", state),
allow_other_host: true) and return
end
unless client_id.present?
redirect_to(url_with_state("#{redirect_uri}#error=invalid_request", state),
allow_other_host: true) and return
end
unless hostname_of(client_id) == hostname_of(redirect_uri)
redirect_to(url_with_state("#{redirect_uri}#error=invalid_client", state),
allow_other_host: true) and return
end
client_id.gsub!(/http(s)?:\/\//, "")
auth = current_user.remote_storage_authorizations.create!(
permissions: permissions,
client_id: client_id,
redirect_uri: redirect_uri,
app_name: client_id, #TODO use user-defined name
expire_at: expire_at
)
redirect_to url_with_state("#{redirect_uri}#access_token=#{auth.token}", state),
allow_other_host: true
end
# GET /rs/oauth/token/:id/launch_app
def launch_app
auth = current_user.remote_storage_authorizations.find(params[:id])
redirect_to app_auth_url(auth), allow_other_host: true
end
private
def require_signed_in_with_username
unless user_signed_in?
username, org = params[:useraddress].split("@")
redirect_to new_user_session_path(cn: username, ou: org)
end
end
def app_auth_url(auth)
url = "#{auth.url}#remotestorage=#{current_user.address}"
url += "&access_token=#{auth.token}"
url
end
def hostname_of(uri)
uri.gsub(/http(s)?:\/\//, "").split(":")[0].split("/")[0]
end
def parse_scopes(scope_string)
return [] if scope_string.blank?
scopes = scope_string.
gsub(/\[|\]/, "").
gsub(/\,/, " ").
gsub(/\/:/, ":").
split(/\s/).map(&:strip).
reject(&:empty?)
scopes = [":r"] if scopes.include?("*:r")
scopes = [":rw"] if scopes.include?("*:rw")
scopes
end
def url_with_state(url, state)
state ? "#{url}&state=#{CGI.escape(state)}" : url
end
end

View File

@@ -0,0 +1,9 @@
class Services::BaseController < ApplicationController
before_action :set_current_section
private
def set_current_section
@current_section = :services
end
end

View File

@@ -0,0 +1,14 @@
class Services::ChatController < Services::BaseController
before_action :authenticate_user!
before_action :require_service_available
def show
@service_enabled = current_user.services_enabled.include?(:xmpp)
end
private
def require_service_available
http_status :not_found unless Setting.ejabberd_enabled?
end
end

View File

@@ -0,0 +1,122 @@
require "rqrcode"
require "lnurl"
class Services::LightningController < ApplicationController
before_action :authenticate_user!
before_action :authenticate_with_lndhub
before_action :set_current_section
before_action :fetch_balance
def index
@wallet_setup_url = "lndhub://#{current_user.ln_account}:#{current_user.ln_password}@#{ENV['LNDHUB_PUBLIC_URL']}"
end
def transactions
@transactions = fetch_transactions
end
def qr_lnurlp
lnurlp_url = "https://kosmos.org/.well-known/lnurlp/#{current_user.cn}"
lnurlp_bech32 = Lnurl.new(lnurlp_url).to_bech32
qr_code = RQRCode::QRCode.new("lightning:" + lnurlp_bech32)
respond_to do |format|
format.svg do
qr_svg = qr_code.as_svg(
color: "000",
shape_rendering: "crispEdges",
module_size: 6,
standalone: true,
use_path: true,
svg_attributes: {
class: 'inline-block'
}
)
send_data(
qr_svg,
filename: "bitcoin-lightning-#{current_user.address}.svg",
type: "image/svg+xml"
)
end
format.png do
qr_png = qr_code.as_png(
fill: "white",
color: "black",
size: 1024,
)
send_data(
qr_png,
filename: "bitcoin-lightning-#{current_user.address}.png",
type: "image/png"
)
end
end
end
private
def authenticate_with_lndhub(options={})
if session[:ln_auth_token].present? && !options[:force_reauth]
@ln_auth_token = session[:ln_auth_token]
else
lndhub = Lndhub.new
auth_token = lndhub.authenticate(current_user)
session[:ln_auth_token] = auth_token
@ln_auth_token = auth_token
end
rescue => e
Sentry.capture_exception(e) if Setting.sentry_enabled?
end
def set_current_section
@current_section = :services
end
def fetch_balance
lndhub = Lndhub.new
data = lndhub.balance @ln_auth_token
@balance = data["BTC"]["AvailableBalance"] rescue nil
rescue AuthError
authenticate_with_lndhub(force_reauth: true)
raise if @fetch_balance_retried
@fetch_balance_retried = true
fetch_balance
end
def fetch_transactions
lndhub = Lndhub.new
txs = lndhub.gettxs @ln_auth_token
invoices = lndhub.getuserinvoices(@ln_auth_token).select{|i| i["ispaid"]}
process_transactions(txs + invoices)
rescue AuthError
authenticate_with_lndhub(force_reauth: true)
raise if @fetch_transactions_retried
@fetch_transactions_retried = true
fetch_transactions
end
def process_transactions(txs)
txs.collect do |tx|
if tx["type"] == "bitcoind_tx"
tx["amount_sats"] = (tx["amount"] * 100000000).to_i
tx["datetime"] = Time.at(tx["time"].to_i)
tx["title"] = "Received"
tx["description"] = "On-chain topup"
tx["received"] = true
else
tx["amount_sats"] = tx["value"] || tx["amt"]
tx["fee"] = tx["type"] == "paid_invoice" ? tx["fee"] : nil
tx["datetime"] = Time.at(tx["timestamp"].to_i)
tx["title"] = tx["type"] == "paid_invoice" ? "Sent" : "Received"
tx["description"] = tx["memo"] || tx["description"]
tx["received"] = tx["type"] == "user_invoice"
end
end
# Handle an edge case where lndhub.go includes a failed payment in the
# list, which wasn't actually booked
txs.reject!{ |tx| tx["type"] == "paid_invoice" && tx["payment_preimage"].blank? }
txs.sort{ |a,b| b["datetime"] <=> a["datetime"] }
end
end

View File

@@ -0,0 +1,14 @@
class Services::MastodonController < Services::BaseController
before_action :authenticate_user!
before_action :require_service_available
def show
@service_enabled = current_user.services_enabled.include?(:mastodon)
end
private
def require_service_available
http_status :not_found unless Setting.mastodon_enabled?
end
end

View File

@@ -0,0 +1,23 @@
class Services::RemotestorageController < Services::BaseController
before_action :authenticate_user!
before_action :require_feature_enabled
before_action :require_service_available
def dashboard
# unless current_user.services_enabled.include?(:remotestorage)
# redirect_to service_remotestorage_info_path
# end
end
private
def require_feature_enabled
unless Flipper.enabled?(:remotestorage, current_user)
http_status :forbidden
end
end
def require_service_available
http_status :not_found unless Setting.remotestorage_enabled?
end
end

View File

@@ -1,7 +1,54 @@
require 'securerandom'
class SettingsController < ApplicationController
before_action :require_user_signed_in
before_action :authenticate_user!
before_action :set_main_nav_section
before_action :set_settings_section, only: [:show, :update, :update_email]
before_action :set_user, only: [:show, :update, :update_email]
def index
redirect_to setting_path(:profile)
end
def show
if @settings_section == "experiments"
session[:shared_secret] ||= SecureRandom.base64(12)
end
end
def update
@user.preferences.merge!(user_params[:preferences] || {})
@user.display_name = user_params[:display_name]
if @user.save
if @user.display_name && (@user.display_name != @user.ldap_entry[:display_name])
LdapManager::UpdateDisplayName.call(@user.dn, user_params[:display_name])
end
redirect_to setting_path(@settings_section), flash: {
success: 'Settings saved.'
}
else
@validation_errors = @user.errors
render :show, status: :unprocessable_entity
end
end
def update_email
if @user.valid_ldap_authentication?(email_params[:current_password])
if @user.update email: email_params[:email]
redirect_to setting_path(:account), flash: {
notice: 'Please confirm your new address using the confirmation link we just sent you.'
}
else
@validation_errors = @user.errors
render :show, status: :unprocessable_entity
end
else
redirect_to setting_path(:account), flash: {
error: 'Password did not match your current password. Try again.'
}
end
end
def reset_password
@@ -10,4 +57,79 @@ class SettingsController < ApplicationController
msg = "We have sent you an email with a link to reset your password."
redirect_to check_your_email_path, notice: msg
end
def set_nostr_pubkey
signed_event = nostr_event_params[:signed_event].to_h.symbolize_keys
is_valid_id = NostrManager::ValidateId.call(signed_event)
is_valid_sig = NostrManager::VerifySignature.call(signed_event)
is_correct_content = signed_event[:content] == "Connect my public key to #{current_user.address} (confirmation #{session[:shared_secret]})"
unless is_valid_id && is_valid_sig && is_correct_content
flash[:alert] = "Public key could not be verified"
http_status :unprocessable_entity and return
end
pubkey_taken = User.all_except(current_user).where(
ou: current_user.ou, nostr_pubkey: signed_event[:pubkey]
).any?
if pubkey_taken
flash[:alert] = "Public key already in use for a different account"
http_status :unprocessable_entity and return
end
current_user.update! nostr_pubkey: signed_event[:pubkey]
session[:shared_secret] = nil
flash[:success] = "Public key verification successful"
http_status :ok
rescue
flash[:alert] = "Public key could not be verified"
http_status :unprocessable_entity and return
end
# DELETE /settings/nostr_pubkey
def remove_nostr_pubkey
current_user.update! nostr_pubkey: nil
redirect_to setting_path(:experiments), flash: {
success: 'Public key removed from account'
}
end
private
def set_main_nav_section
@current_section = :settings
end
def set_settings_section
@settings_section = params[:section]
allowed_sections = [:profile, :account, :lightning, :xmpp, :experiments]
unless allowed_sections.include?(@settings_section.to_sym)
redirect_to setting_path(:profile)
end
end
def set_user
@user = current_user
end
def user_params
params.require(:user).permit(:display_name, preferences: [
:lightning_notify_sats_received,
:xmpp_exchange_contacts_with_invitees
])
end
def email_params
params.require(:user).permit(:email, :current_password)
end
def nostr_event_params
params.permit(signed_event: [
:id, :pubkey, :created_at, :kind, :tags, :content, :sig
])
end
end

View File

@@ -0,0 +1,111 @@
class SignupController < ApplicationController
before_action :require_user_signed_out
before_action :require_invitation
before_action :set_invitation
before_action :set_new_user, only: ["steps", "validate"]
before_action :set_context
def index
@invited_by_name = @invitation.user.address
end
def steps
@step = params[:step].to_i
http_status :not_found unless [1,2,3].include?(@step)
@validation_error = session[:validation_error]
end
def validate
session[:validation_error] = nil
case user_params.keys.first
when "cn"
@user.cn = user_params[:cn]
@user.valid?
session[:new_user] = @user
if @user.errors[:cn].present?
session[:validation_error] = @user.errors[:cn].first # Store user including validation errors
redirect_to signup_steps_path(1) and return
else
redirect_to signup_steps_path(2) and return
end
when "email"
@user.email = user_params[:email]
@user.valid?
session[:new_user] = @user
if @user.errors[:email].present?
session[:validation_error] = @user.errors[:email].first # Store user including validation errors
redirect_to signup_steps_path(2) and return
else
redirect_to signup_steps_path(3) and return
end
when "password"
@user.password = user_params[:password]
@user.password_confirmation = user_params[:password]
@user.valid?
session[:new_user] = @user
if @user.errors[:password].present?
session[:validation_error] = @user.errors[:password].first # Store user including validation errors
redirect_to signup_steps_path(3) and return
else
complete_signup
msg = "Almost done! We have sent you an email to confirm your address."
redirect_to(check_your_email_path, notice: msg) and return
end
end
end
private
def user_params
params.require(:user).permit(:cn, :email, :password)
end
def require_invitation
if session[:invitation_token].blank?
flash.now[:alert] = "You need an invitation to sign up for an account."
http_status :unauthorized
elsif !valid_invitation?(session[:invitation_token])
flash.now[:alert] = "This invitation either doesn't exist or has already been used."
http_status :unauthorized
end
@invitation = Invitation.find_by(token: session[:invitation_token])
end
def valid_invitation?(token)
Invitation.where(token: session[:invitation_token], used_at: nil).exists?
end
def set_invitation
@invitation = Invitation.find_by(token: session[:invitation_token])
end
def set_new_user
if session[:new_user].present?
@user = User.new(session[:new_user])
else
@user = User.new(ou: Setting.primary_domain)
end
end
def complete_signup
session[:new_user] = nil
session[:validation_error] = nil
CreateAccount.call(
username: @user.cn,
domain: Setting.primary_domain,
email: @user.email,
password: @user.password,
invitation: @invitation
)
end
def set_context
@context = :signup
end
end

View File

@@ -0,0 +1,18 @@
class TurboController < ApplicationController
class Responder < ActionController::Responder
def to_turbo_stream
controller.render(options.merge(formats: :html))
rescue ActionView::MissingTemplate => error
if get?
raise error
elsif has_errors? && default_action
render rendering_options.merge(formats: :html, status: :unprocessable_entity)
else
redirect_to navigation_location
end
end
end
self.responder = Responder
respond_to :html, :turbo_stream
end

View File

@@ -0,0 +1,17 @@
# frozen_string_literal: true
class Users::ConfirmationsController < Devise::ConfirmationsController
# GET /resource/confirmation?confirmation_token=abcdef
def show
self.resource = resource_class.confirm_by_token(params[:confirmation_token])
yield resource if block_given?
if resource.errors.empty?
set_flash_message!(:success, :confirmed)
resource.devise_after_confirmation
respond_with_navigational(resource){ redirect_to after_confirmation_path_for(resource_name, resource) }
else
respond_with_navigational(resource.errors, status: :unprocessable_entity){ render :new }
end
end
end

View File

@@ -0,0 +1,18 @@
class Users::DeviseController < ApplicationController
class Responder < ActionController::Responder
def to_turbo_stream
controller.render(options.merge(formats: :html))
rescue ActionView::MissingTemplate => error
if get?
raise error
elsif has_errors? && default_action
render rendering_options.merge(formats: :html, status: :unprocessable_entity)
else
redirect_to navigation_location
end
end
end
self.responder = Responder
respond_to :html, :turbo_stream
end

View File

@@ -0,0 +1,57 @@
class WebfingerController < ApplicationController
before_action :allow_cross_origin_requests, only: [:show]
layout false
def show
resource = params[:resource]
if resource && resource.match(/acct:\w+/)
useraddress = resource.split(":").last
username, org = useraddress.split("@")
username.downcase!
unless User.where(cn: username, ou: org).any?
head 404 and return
end
render json: webfinger(useraddress).to_json,
content_type: "application/jrd+json"
else
head 422 and return
end
end
private
def webfinger(useraddress)
links = [];
links << remotestorage_link(useraddress) if Setting.remotestorage_enabled
{ "links" => links }
end
def remotestorage_link(useraddress)
# TODO use when OAuth routes are available
# auth_url = new_rs_oauth_url(useraddress)
auth_url = "https://example.com/rs/oauth"
storage_url = "#{Setting.rs_storage_url}/#{useraddress}"
{
"rel" => "http://tools.ietf.org/id/draft-dejong-remotestorage",
"href" => storage_url,
"properties" => {
"http://remotestorage.io/spec/version" => "draft-dejong-remotestorage-13",
"http://tools.ietf.org/html/rfc6749#section-4.2" => auth_url,
"http://tools.ietf.org/html/rfc6750#section-2.3" => nil, # access token via a HTTP query parameter
"http://tools.ietf.org/html/rfc7233": "GET", # content range requests
"http://remotestorage.io/spec/web-authoring": nil
}
}
end
def allow_cross_origin_requests
headers['Access-Control-Allow-Origin'] = '*'
headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, OPTIONS'
end
end

View File

@@ -0,0 +1,46 @@
class WebhooksController < ApplicationController
skip_forgery_protection
before_action :authorize_request
def lndhub
begin
payload = JSON.parse(request.body.read, symbolize_names: true)
head :no_content and return unless payload[:type] == "incoming"
rescue
head :unprocessable_entity and return
end
user = User.find_by!(ln_account: payload[:user_login])
notify = user.preferences[:lightning_notify_sats_received]
case notify
when "xmpp"
notify_xmpp(user.address, payload[:amount], payload[:memo])
when "email"
NotificationMailer.with(user: user, amount_sats: payload[:amount])
.lightning_sats_received.deliver_later
end
head :ok
end
private
# TODO refactor into mailer-like generic class/service
def notify_xmpp(address, amt_sats, memo)
payload = {
type: "normal",
from: Setting.primary_domain,
to: address,
subject: "Sats received!",
body: "#{helpers.number_with_delimiter amt_sats} sats received in your Lightning wallet:\n> #{memo}"
}
XmppSendMessageJob.perform_later(payload)
end
def authorize_request
if !ENV['WEBHOOKS_ALLOWED_IPS'].split(',').include?(request.remote_ip)
head :forbidden and return
end
end
end

Some files were not shown because too many files have changed in this diff Show More