Merge pull request 'Docker Compose config, local 389ds/dirsrv, LDAP and user seeds' (#74) from feature/docker_compose into master
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
Reviewed-on: #74
This commit is contained in:
commit
2e1d930e0f
|
@ -17,7 +17,7 @@ steps:
|
|||
branch:
|
||||
- master
|
||||
- name: rspec
|
||||
image: guildeducation/rails:2.7.2-12.22.0
|
||||
image: guildeducation/rails:2.7.2-14.20.0
|
||||
environment:
|
||||
RAILS_ENV: test
|
||||
commands:
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
LDAP_HOST=localhost
|
||||
LDAP_PORT=389
|
||||
LDAP_ADMIN_PASSWORD=passthebutter
|
||||
LDAP_SUFFIX="dc=kosmos,dc=org"
|
||||
|
||||
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'
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
EJABBERD_API_URL='https://xmpp.kosmos.org:5443/api'
|
||||
|
||||
BTCPAY_API_URL='http://10.1.1.163:23001/api/v1'
|
||||
LNDHUB_API_URL='http://10.1.1.163:3023'
|
||||
|
||||
LNDHUB_LEGACY_API_URL='http://10.1.1.163:3026'
|
||||
LNDHUB_API_URL='http://10.1.1.163:3026'
|
||||
LNDHUB_PUBLIC_URL='https://lndhub.kosmos.org'
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
EJABBERD_API_URL='http://xmpp.example.com/api'
|
||||
BTCPAY_API_URL='http://btcpay.example.com/api/v1'
|
||||
LNDHUB_API_URL='http://localhost:3023'
|
||||
LNDHUB_LEGACY_API_URL='http://localhost:3023'
|
||||
LNDHUB_API_URL='http://localhost:3026'
|
||||
LNDHUB_PUBLIC_URL='https://lndhub.kosmos.org'
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
# syntax=docker/dockerfile:1
|
||||
FROM ruby:2.7.6
|
||||
RUN apt-get update -qq && apt-get install -y curl ldap-utils
|
||||
RUN curl -fsSL https://deb.nodesource.com/setup_lts.x | bash -
|
||||
RUN apt-get update && apt-get install -y nodejs
|
||||
WORKDIR /akkounts
|
||||
COPY Gemfile /akkounts/Gemfile
|
||||
COPY Gemfile.lock /akkounts/Gemfile.lock
|
||||
COPY package.json /akkounts/package.json
|
||||
RUN bundle install
|
||||
RUN npm install -g yarn
|
||||
RUN yarn install
|
||||
|
||||
# Add a script to be executed every time the container starts.
|
||||
COPY docker/entrypoint.sh /usr/bin/
|
||||
RUN chmod +x /usr/bin/entrypoint.sh
|
||||
ENTRYPOINT ["entrypoint.sh"]
|
||||
EXPOSE 3000
|
||||
|
||||
# Configure the main process to run when running the image
|
||||
CMD ["bin", "dev"]
|
4
Gemfile
4
Gemfile
|
@ -43,13 +43,14 @@ gem "rqrcode", "~> 2.0"
|
|||
gem 'faraday'
|
||||
|
||||
# Background/scheduled jobs
|
||||
gem 'sidekiq'
|
||||
gem 'sidekiq', '< 7'
|
||||
gem 'sidekiq-scheduler'
|
||||
|
||||
group :development, :test do
|
||||
# Use sqlite3 as the database for Active Record
|
||||
gem 'sqlite3', '~> 1.4'
|
||||
gem 'rspec-rails'
|
||||
gem "byebug", "~> 11.1"
|
||||
end
|
||||
|
||||
group :development do
|
||||
|
@ -58,6 +59,7 @@ group :development do
|
|||
gem 'listen', '~> 3.2'
|
||||
gem 'letter_opener'
|
||||
gem 'letter_opener_web'
|
||||
gem 'faker'
|
||||
end
|
||||
|
||||
group :test do
|
||||
|
|
228
Gemfile.lock
228
Gemfile.lock
|
@ -1,77 +1,78 @@
|
|||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
actioncable (7.0.3.1)
|
||||
actionpack (= 7.0.3.1)
|
||||
activesupport (= 7.0.3.1)
|
||||
actioncable (7.0.4)
|
||||
actionpack (= 7.0.4)
|
||||
activesupport (= 7.0.4)
|
||||
nio4r (~> 2.0)
|
||||
websocket-driver (>= 0.6.1)
|
||||
actionmailbox (7.0.3.1)
|
||||
actionpack (= 7.0.3.1)
|
||||
activejob (= 7.0.3.1)
|
||||
activerecord (= 7.0.3.1)
|
||||
activestorage (= 7.0.3.1)
|
||||
activesupport (= 7.0.3.1)
|
||||
actionmailbox (7.0.4)
|
||||
actionpack (= 7.0.4)
|
||||
activejob (= 7.0.4)
|
||||
activerecord (= 7.0.4)
|
||||
activestorage (= 7.0.4)
|
||||
activesupport (= 7.0.4)
|
||||
mail (>= 2.7.1)
|
||||
net-imap
|
||||
net-pop
|
||||
net-smtp
|
||||
actionmailer (7.0.3.1)
|
||||
actionpack (= 7.0.3.1)
|
||||
actionview (= 7.0.3.1)
|
||||
activejob (= 7.0.3.1)
|
||||
activesupport (= 7.0.3.1)
|
||||
actionmailer (7.0.4)
|
||||
actionpack (= 7.0.4)
|
||||
actionview (= 7.0.4)
|
||||
activejob (= 7.0.4)
|
||||
activesupport (= 7.0.4)
|
||||
mail (~> 2.5, >= 2.5.4)
|
||||
net-imap
|
||||
net-pop
|
||||
net-smtp
|
||||
rails-dom-testing (~> 2.0)
|
||||
actionpack (7.0.3.1)
|
||||
actionview (= 7.0.3.1)
|
||||
activesupport (= 7.0.3.1)
|
||||
actionpack (7.0.4)
|
||||
actionview (= 7.0.4)
|
||||
activesupport (= 7.0.4)
|
||||
rack (~> 2.0, >= 2.2.0)
|
||||
rack-test (>= 0.6.3)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
||||
actiontext (7.0.3.1)
|
||||
actionpack (= 7.0.3.1)
|
||||
activerecord (= 7.0.3.1)
|
||||
activestorage (= 7.0.3.1)
|
||||
activesupport (= 7.0.3.1)
|
||||
actiontext (7.0.4)
|
||||
actionpack (= 7.0.4)
|
||||
activerecord (= 7.0.4)
|
||||
activestorage (= 7.0.4)
|
||||
activesupport (= 7.0.4)
|
||||
globalid (>= 0.6.0)
|
||||
nokogiri (>= 1.8.5)
|
||||
actionview (7.0.3.1)
|
||||
activesupport (= 7.0.3.1)
|
||||
actionview (7.0.4)
|
||||
activesupport (= 7.0.4)
|
||||
builder (~> 3.1)
|
||||
erubi (~> 1.4)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
||||
activejob (7.0.3.1)
|
||||
activesupport (= 7.0.3.1)
|
||||
activejob (7.0.4)
|
||||
activesupport (= 7.0.4)
|
||||
globalid (>= 0.3.6)
|
||||
activemodel (7.0.3.1)
|
||||
activesupport (= 7.0.3.1)
|
||||
activerecord (7.0.3.1)
|
||||
activemodel (= 7.0.3.1)
|
||||
activesupport (= 7.0.3.1)
|
||||
activestorage (7.0.3.1)
|
||||
actionpack (= 7.0.3.1)
|
||||
activejob (= 7.0.3.1)
|
||||
activerecord (= 7.0.3.1)
|
||||
activesupport (= 7.0.3.1)
|
||||
activemodel (7.0.4)
|
||||
activesupport (= 7.0.4)
|
||||
activerecord (7.0.4)
|
||||
activemodel (= 7.0.4)
|
||||
activesupport (= 7.0.4)
|
||||
activestorage (7.0.4)
|
||||
actionpack (= 7.0.4)
|
||||
activejob (= 7.0.4)
|
||||
activerecord (= 7.0.4)
|
||||
activesupport (= 7.0.4)
|
||||
marcel (~> 1.0)
|
||||
mini_mime (>= 1.1.0)
|
||||
activesupport (7.0.3.1)
|
||||
activesupport (7.0.4)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (>= 1.6, < 2)
|
||||
minitest (>= 5.1)
|
||||
tzinfo (~> 2.0)
|
||||
addressable (2.8.0)
|
||||
public_suffix (>= 2.0.2, < 5.0)
|
||||
addressable (2.8.1)
|
||||
public_suffix (>= 2.0.2, < 6.0)
|
||||
bcrypt (3.1.18)
|
||||
bindex (0.8.1)
|
||||
builder (3.2.4)
|
||||
capybara (3.37.1)
|
||||
byebug (11.1.3)
|
||||
capybara (3.38.0)
|
||||
addressable
|
||||
matrix
|
||||
mini_mime (>= 0.1.3)
|
||||
|
@ -82,7 +83,7 @@ GEM
|
|||
xpath (~> 3.2)
|
||||
chunky_png (1.4.0)
|
||||
concurrent-ruby (1.1.10)
|
||||
connection_pool (2.2.5)
|
||||
connection_pool (2.3.0)
|
||||
crack (0.4.5)
|
||||
rexml
|
||||
crass (1.0.6)
|
||||
|
@ -104,12 +105,11 @@ GEM
|
|||
devise (>= 3.4.1)
|
||||
net-ldap (>= 0.16.0)
|
||||
diff-lcs (1.5.0)
|
||||
digest (3.1.0)
|
||||
dotenv (2.8.0)
|
||||
dotenv-rails (2.8.0)
|
||||
dotenv (= 2.8.0)
|
||||
dotenv (2.8.1)
|
||||
dotenv-rails (2.8.1)
|
||||
dotenv (= 2.8.1)
|
||||
railties (>= 3.2)
|
||||
erubi (1.10.0)
|
||||
erubi (1.11.0)
|
||||
et-orbi (1.2.7)
|
||||
tzinfo
|
||||
factory_bot (6.2.1)
|
||||
|
@ -117,12 +117,14 @@ GEM
|
|||
factory_bot_rails (6.2.0)
|
||||
factory_bot (~> 6.2.0)
|
||||
railties (>= 5.0.0)
|
||||
faraday (2.3.0)
|
||||
faraday-net_http (~> 2.0)
|
||||
faker (3.0.0)
|
||||
i18n (>= 1.8.11, < 2)
|
||||
faraday (2.7.1)
|
||||
faraday-net_http (>= 2.0, < 3.1)
|
||||
ruby2_keywords (>= 0.0.4)
|
||||
faraday-net_http (2.0.3)
|
||||
faraday-net_http (3.0.2)
|
||||
ffi (1.15.5)
|
||||
fugit (1.5.3)
|
||||
fugit (1.7.2)
|
||||
et-orbi (~> 1, >= 1.2.7)
|
||||
raabro (~> 1.4)
|
||||
globalid (1.0.0)
|
||||
|
@ -148,8 +150,8 @@ GEM
|
|||
listen (3.7.1)
|
||||
rb-fsevent (~> 0.10, >= 0.10.3)
|
||||
rb-inotify (~> 0.9, >= 0.9.10)
|
||||
lockbox (1.0.0)
|
||||
loofah (2.18.0)
|
||||
lockbox (1.1.0)
|
||||
loofah (2.19.0)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.5.9)
|
||||
mail (2.7.1)
|
||||
|
@ -158,28 +160,26 @@ GEM
|
|||
matrix (0.4.2)
|
||||
method_source (1.0.0)
|
||||
mini_mime (1.1.2)
|
||||
minitest (5.16.2)
|
||||
net-imap (0.2.3)
|
||||
digest
|
||||
mini_portile2 (2.8.0)
|
||||
minitest (5.16.3)
|
||||
net-imap (0.3.1)
|
||||
net-protocol
|
||||
strscan
|
||||
net-ldap (0.17.1)
|
||||
net-pop (0.1.1)
|
||||
digest
|
||||
net-pop (0.1.2)
|
||||
net-protocol
|
||||
timeout
|
||||
net-protocol (0.1.3)
|
||||
timeout
|
||||
net-smtp (0.3.1)
|
||||
digest
|
||||
net-smtp (0.3.3)
|
||||
net-protocol
|
||||
timeout
|
||||
nio4r (2.5.8)
|
||||
nokogiri (1.13.8-x86_64-linux)
|
||||
nokogiri (1.13.9)
|
||||
mini_portile2 (~> 2.8.0)
|
||||
racc (~> 1.4)
|
||||
nokogiri (1.13.9-x86_64-linux)
|
||||
racc (~> 1.4)
|
||||
orm_adapter (0.5.0)
|
||||
pg (1.2.3)
|
||||
public_suffix (4.0.7)
|
||||
public_suffix (5.0.0)
|
||||
puma (4.3.12)
|
||||
nio4r (~> 2.0)
|
||||
raabro (1.4.0)
|
||||
|
@ -187,38 +187,41 @@ GEM
|
|||
rack (2.2.4)
|
||||
rack-test (2.0.2)
|
||||
rack (>= 1.3)
|
||||
rails (7.0.3.1)
|
||||
actioncable (= 7.0.3.1)
|
||||
actionmailbox (= 7.0.3.1)
|
||||
actionmailer (= 7.0.3.1)
|
||||
actionpack (= 7.0.3.1)
|
||||
actiontext (= 7.0.3.1)
|
||||
actionview (= 7.0.3.1)
|
||||
activejob (= 7.0.3.1)
|
||||
activemodel (= 7.0.3.1)
|
||||
activerecord (= 7.0.3.1)
|
||||
activestorage (= 7.0.3.1)
|
||||
activesupport (= 7.0.3.1)
|
||||
rails (7.0.4)
|
||||
actioncable (= 7.0.4)
|
||||
actionmailbox (= 7.0.4)
|
||||
actionmailer (= 7.0.4)
|
||||
actionpack (= 7.0.4)
|
||||
actiontext (= 7.0.4)
|
||||
actionview (= 7.0.4)
|
||||
activejob (= 7.0.4)
|
||||
activemodel (= 7.0.4)
|
||||
activerecord (= 7.0.4)
|
||||
activestorage (= 7.0.4)
|
||||
activesupport (= 7.0.4)
|
||||
bundler (>= 1.15.0)
|
||||
railties (= 7.0.3.1)
|
||||
railties (= 7.0.4)
|
||||
rails-dom-testing (2.0.3)
|
||||
activesupport (>= 4.2.0)
|
||||
nokogiri (>= 1.6)
|
||||
rails-html-sanitizer (1.4.3)
|
||||
loofah (~> 2.3)
|
||||
railties (7.0.3.1)
|
||||
actionpack (= 7.0.3.1)
|
||||
activesupport (= 7.0.3.1)
|
||||
railties (7.0.4)
|
||||
actionpack (= 7.0.4)
|
||||
activesupport (= 7.0.4)
|
||||
method_source
|
||||
rake (>= 12.2)
|
||||
thor (~> 1.0)
|
||||
zeitwerk (~> 2.5)
|
||||
rake (13.0.6)
|
||||
rb-fsevent (0.11.1)
|
||||
rb-fsevent (0.11.2)
|
||||
rb-inotify (0.10.1)
|
||||
ffi (~> 1.0)
|
||||
redis (4.7.1)
|
||||
regexp_parser (2.5.0)
|
||||
redis (5.0.5)
|
||||
redis-client (>= 0.9.0)
|
||||
redis-client (0.11.2)
|
||||
connection_pool
|
||||
regexp_parser (2.6.1)
|
||||
responders (3.0.1)
|
||||
actionpack (>= 5.0)
|
||||
railties (>= 5.0)
|
||||
|
@ -227,34 +230,34 @@ GEM
|
|||
chunky_png (~> 1.0)
|
||||
rqrcode_core (~> 1.0)
|
||||
rqrcode_core (1.2.0)
|
||||
rspec-core (3.11.0)
|
||||
rspec-support (~> 3.11.0)
|
||||
rspec-expectations (3.11.0)
|
||||
rspec-core (3.12.0)
|
||||
rspec-support (~> 3.12.0)
|
||||
rspec-expectations (3.12.0)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.11.0)
|
||||
rspec-mocks (3.11.1)
|
||||
rspec-support (~> 3.12.0)
|
||||
rspec-mocks (3.12.0)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.11.0)
|
||||
rspec-rails (5.1.2)
|
||||
actionpack (>= 5.2)
|
||||
activesupport (>= 5.2)
|
||||
railties (>= 5.2)
|
||||
rspec-core (~> 3.10)
|
||||
rspec-expectations (~> 3.10)
|
||||
rspec-mocks (~> 3.10)
|
||||
rspec-support (~> 3.10)
|
||||
rspec-support (3.11.0)
|
||||
rspec-support (~> 3.12.0)
|
||||
rspec-rails (6.0.1)
|
||||
actionpack (>= 6.1)
|
||||
activesupport (>= 6.1)
|
||||
railties (>= 6.1)
|
||||
rspec-core (~> 3.11)
|
||||
rspec-expectations (~> 3.11)
|
||||
rspec-mocks (~> 3.11)
|
||||
rspec-support (~> 3.11)
|
||||
rspec-support (3.12.0)
|
||||
ruby2_keywords (0.0.5)
|
||||
rufus-scheduler (3.8.2)
|
||||
fugit (~> 1.1, >= 1.1.6)
|
||||
sidekiq (6.5.1)
|
||||
sidekiq (6.5.5)
|
||||
connection_pool (>= 2.2.2)
|
||||
rack (~> 2.0)
|
||||
redis (>= 4.2.0)
|
||||
sidekiq-scheduler (4.0.2)
|
||||
redis (>= 4.5.0)
|
||||
sidekiq-scheduler (4.0.3)
|
||||
redis (>= 4.2.0)
|
||||
rufus-scheduler (~> 3.2)
|
||||
sidekiq (>= 4)
|
||||
sidekiq (>= 4, < 7)
|
||||
tilt (>= 1.4.0)
|
||||
sprockets (4.1.1)
|
||||
concurrent-ruby (~> 1.0)
|
||||
|
@ -263,21 +266,23 @@ GEM
|
|||
actionpack (>= 5.2)
|
||||
activesupport (>= 5.2)
|
||||
sprockets (>= 3.0.0)
|
||||
sqlite3 (1.4.4)
|
||||
stimulus-rails (1.1.0)
|
||||
sqlite3 (1.5.4)
|
||||
mini_portile2 (~> 2.8.0)
|
||||
sqlite3 (1.5.4-x86_64-linux)
|
||||
stimulus-rails (1.2.1)
|
||||
railties (>= 6.0.0)
|
||||
strscan (3.0.4)
|
||||
thor (1.2.1)
|
||||
tilt (2.0.11)
|
||||
timeout (0.3.0)
|
||||
turbo-rails (1.1.1)
|
||||
turbo-rails (1.3.2)
|
||||
actionpack (>= 6.0.0)
|
||||
activejob (>= 6.0.0)
|
||||
railties (>= 6.0.0)
|
||||
tzinfo (2.0.5)
|
||||
concurrent-ruby (~> 1.0)
|
||||
view_component (2.62.0)
|
||||
view_component (2.78.0)
|
||||
activesupport (>= 5.0.0, < 8.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
method_source (~> 1.0)
|
||||
warden (1.2.9)
|
||||
rack (>= 2.0.9)
|
||||
|
@ -286,7 +291,7 @@ GEM
|
|||
activemodel (>= 6.0.0)
|
||||
bindex (>= 0.4.0)
|
||||
railties (>= 6.0.0)
|
||||
webmock (3.14.0)
|
||||
webmock (3.18.1)
|
||||
addressable (>= 2.8.0)
|
||||
crack (>= 0.3.2)
|
||||
hashdiff (>= 0.4.0, < 2.0.0)
|
||||
|
@ -295,12 +300,14 @@ GEM
|
|||
websocket-extensions (0.1.5)
|
||||
xpath (3.2.0)
|
||||
nokogiri (~> 1.8)
|
||||
zeitwerk (2.6.0)
|
||||
zeitwerk (2.6.6)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
x86_64-linux
|
||||
|
||||
DEPENDENCIES
|
||||
byebug (~> 11.1)
|
||||
capybara
|
||||
cssbundling-rails
|
||||
database_cleaner
|
||||
|
@ -308,6 +315,7 @@ DEPENDENCIES
|
|||
devise_ldap_authenticatable
|
||||
dotenv-rails
|
||||
factory_bot_rails
|
||||
faker
|
||||
faraday
|
||||
importmap-rails
|
||||
jbuilder (~> 2.7)
|
||||
|
@ -321,7 +329,7 @@ DEPENDENCIES
|
|||
rails (~> 7.0.2)
|
||||
rqrcode (~> 2.0)
|
||||
rspec-rails
|
||||
sidekiq
|
||||
sidekiq (< 7)
|
||||
sidekiq-scheduler
|
||||
sprockets-rails
|
||||
sqlite3 (~> 1.4)
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
web: bin/rails server -p 3000
|
||||
web: bin/rails server -b 0.0.0.0 -p 3000
|
||||
css: yarn build:css --watch
|
||||
|
|
51
README.md
51
README.md
|
@ -7,6 +7,27 @@ credentials, invites, donations, etc..
|
|||
|
||||
## Development
|
||||
|
||||
### Quick Start
|
||||
|
||||
The easiest way to get a working development setup is using Docker Compose like
|
||||
so:
|
||||
|
||||
1. Make sure [Docker Compose is installed][1] and Docker is running (included in
|
||||
Docker Desktop)
|
||||
2. Uncomment the `web` section in `docker-compose.yml`
|
||||
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`
|
||||
5. `docker compose run web rails db:setup`
|
||||
|
||||
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/ldap_users](http://localhost:3000/admin/ldap_users)
|
||||
have the password "user is user".
|
||||
|
||||
### Rails app
|
||||
|
||||
Installing dependencies:
|
||||
|
@ -31,10 +52,32 @@ Running all specs:
|
|||
|
||||
bundle exec rspec
|
||||
|
||||
### LDAP server
|
||||
### Docker (Compose)
|
||||
|
||||
TODO make it easy to run a local Kosmos LDAP server for development, without
|
||||
manual LDIF imports etc. (or provide a staging instance)
|
||||
There is a working Docker Compose config file, which allows you to spin up both
|
||||
an app server for Rails as well as a local 389ds (LDAP) server.
|
||||
|
||||
By default, `docker-compose up` will only start the LDAP server, listening on
|
||||
port 389 on your machine. Uncomment other services in `docker-compose.yml` if
|
||||
you want to use them.
|
||||
|
||||
#### 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.
|
||||
|
||||
## Documentation
|
||||
|
||||
|
@ -63,3 +106,5 @@ manual LDIF imports etc. (or provide a staging instance)
|
|||
## License
|
||||
|
||||
[GNU Affero General Public License v3.0](https://choosealicense.com/licenses/agpl-3.0/)
|
||||
|
||||
[1]: https://docs.docker.com/compose/install/
|
||||
|
|
|
@ -27,7 +27,7 @@ class Admin::LdapUsersController < Admin::BaseController
|
|||
def ldap_client
|
||||
ldap_client ||= Net::LDAP.new host: ldap_config['host'],
|
||||
port: ldap_config['port'],
|
||||
encryption: ldap_config['ssl'],
|
||||
# encryption: ldap_config['ssl'],
|
||||
auth: {
|
||||
method: :simple,
|
||||
username: ldap_config['admin_user'],
|
||||
|
|
|
@ -28,13 +28,13 @@ class WalletController < ApplicationController
|
|||
|
||||
private
|
||||
|
||||
def authenticate_with_lndhub
|
||||
if session["ln_auth_token"].present?
|
||||
@ln_auth_token = session["ln_auth_token"]
|
||||
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
|
||||
session[:ln_auth_token] = auth_token
|
||||
@ln_auth_token = auth_token
|
||||
end
|
||||
rescue
|
||||
|
@ -49,14 +49,23 @@ class WalletController < ApplicationController
|
|||
lndhub = Lndhub.new
|
||||
data = lndhub.balance @ln_auth_token
|
||||
@balance = data["BTC"]["AvailableBalance"] rescue nil
|
||||
rescue
|
||||
authenticate_with_lndhub(force_reauth: true)
|
||||
return nil 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
|
||||
authenticate_with_lndhub(force_reauth: true)
|
||||
return [] if @fetch_transactions_retried
|
||||
@fetch_transactions_retried = true
|
||||
fetch_transactions
|
||||
end
|
||||
|
||||
def process_transactions(txs)
|
||||
|
|
|
@ -18,7 +18,7 @@ class CreateLdapUserJob < ApplicationJob
|
|||
def ldap_client
|
||||
ldap_client ||= Net::LDAP.new host: ldap_config['host'],
|
||||
port: ldap_config['port'],
|
||||
encryption: ldap_config['ssl'],
|
||||
# encryption: ldap_config['ssl'],
|
||||
auth: {
|
||||
method: :simple,
|
||||
username: ldap_config['admin_user'],
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
class CreateLndhubWalletJob < ApplicationJob
|
||||
class CreateLndhubAccountJob < ApplicationJob
|
||||
queue_as :default
|
||||
|
||||
def perform(user)
|
||||
return if user.ln_login.present? && user.ln_password.present?
|
||||
|
||||
lndhub = Lndhub.new
|
||||
credentials = lndhub.create({ partnerid: user.ou, accounttype: "user" })
|
||||
lndhub = LndhubV2.new
|
||||
credentials = lndhub.create_account
|
||||
|
||||
user.update! ln_login: credentials["login"],
|
||||
ln_password: credentials["password"]
|
|
@ -5,12 +5,13 @@ class CreateAccount < ApplicationService
|
|||
@email = args[:email]
|
||||
@password = args[:password]
|
||||
@invitation = args[:invitation]
|
||||
@confirmed = args[:confirmed]
|
||||
end
|
||||
|
||||
def call
|
||||
user = create_user_in_database
|
||||
add_ldap_document
|
||||
create_lndhub_wallet(user)
|
||||
create_lndhub_account(user)
|
||||
|
||||
if @invitation.present?
|
||||
update_invitation(user.id)
|
||||
|
@ -26,7 +27,8 @@ class CreateAccount < ApplicationService
|
|||
ou: @domain,
|
||||
email: @email,
|
||||
password: @password,
|
||||
password_confirmation: @password
|
||||
password_confirmation: @password,
|
||||
confirmed_at: @confirmed ? DateTime.now : nil
|
||||
)
|
||||
end
|
||||
|
||||
|
@ -35,6 +37,7 @@ class CreateAccount < ApplicationService
|
|||
end
|
||||
|
||||
# TODO move to confirmation
|
||||
# (and/or add email_confirmed to entry and use in login filter)
|
||||
def add_ldap_document
|
||||
hashed_pw = Devise.ldap_auth_password_builder.call(@password)
|
||||
CreateLdapUserJob.perform_later(@username, @domain, @email, hashed_pw)
|
||||
|
@ -46,21 +49,9 @@ class CreateAccount < ApplicationService
|
|||
ExchangeXmppContactsJob.perform_later(@invitation.user, @username, @domain)
|
||||
end
|
||||
|
||||
def create_lndhub_wallet(user)
|
||||
CreateLndhubWalletJob.perform_later(user)
|
||||
end
|
||||
|
||||
def exchange_xmpp_contacts_between_inviter_and_invitee
|
||||
ejabberd = EjabberdApiClient.new
|
||||
|
||||
EjabberdApiClient.add_roster_item({
|
||||
"localuser": @username,
|
||||
"localhost": @domain,
|
||||
"user": @inviter.cn,
|
||||
"host": @inviter.ou,
|
||||
"nick": @username,
|
||||
"group": "Friends",
|
||||
"subs": "both"
|
||||
})
|
||||
def create_lndhub_account(user)
|
||||
#TODO enable in development when we have a local lndhub (mock?) API
|
||||
return if Rails.env.development?
|
||||
CreateLndhubAccountJob.perform_later(user)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,135 @@
|
|||
class LdapService < ApplicationService
|
||||
def initialize
|
||||
@suffix = ENV["LDAP_SUFFIX"] || "dc=kosmos,dc=org"
|
||||
end
|
||||
|
||||
def add_entry(dn, attrs, interactive=false)
|
||||
puts "Adding entry: #{dn}" if interactive
|
||||
res = ldap_client.add dn: dn, attributes: attrs
|
||||
puts res.inspect if interactive && !res
|
||||
res
|
||||
end
|
||||
|
||||
def add_attribute(dn, attr, value)
|
||||
ldap_client.add_attribute dn, attr, value
|
||||
end
|
||||
|
||||
def delete_entry(dn, interactive=false)
|
||||
puts "Deleting entry: #{dn}" if interactive
|
||||
res = ldap_client.delete dn: dn
|
||||
puts res.inspect if interactive && !res
|
||||
res
|
||||
end
|
||||
|
||||
def delete_all_entries!
|
||||
if Rails.env.production?
|
||||
raise "Mass deletion of entries not allowed in production"
|
||||
end
|
||||
|
||||
filter = Net::LDAP::Filter.eq("objectClass", "*")
|
||||
entries = ldap_client.search(base: @suffix, filter: filter, attributes: %w{dn})
|
||||
entries.sort_by!{ |e| e.dn.length }.reverse!
|
||||
|
||||
entries.each do |e|
|
||||
delete_entry e.dn, true
|
||||
end
|
||||
end
|
||||
|
||||
def fetch_users(args={})
|
||||
if args[:ou]
|
||||
treebase = "ou=#{args[:ou]},cn=users,#{@suffix}"
|
||||
else
|
||||
treebase = ldap_config["base"]
|
||||
end
|
||||
|
||||
attributes = %w{dn cn uid mail admin}
|
||||
filter = Net::LDAP::Filter.eq("uid", "*")
|
||||
|
||||
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
|
||||
end
|
||||
|
||||
def fetch_organizations
|
||||
attributes = %w{dn ou description}
|
||||
filter = Net::LDAP::Filter.eq("objectClass", "organizationalUnit")
|
||||
# filter = Net::LDAP::Filter.eq("objectClass", "*")
|
||||
treebase = "cn=users,#{@suffix}"
|
||||
|
||||
entries = ldap_client.search(base: treebase, filter: filter, attributes: attributes)
|
||||
|
||||
entries.sort_by! { |e| e.ou[0] }
|
||||
|
||||
entries = entries.collect do |e|
|
||||
{
|
||||
dn: e.dn,
|
||||
ou: e.ou.first,
|
||||
description: e.try(:description) ? e.description.first : nil,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def add_organization(ou, description, interactive=false)
|
||||
dn = "ou=#{ou},cn=users,#{@suffix}"
|
||||
|
||||
aci = <<-EOS
|
||||
(target="ldap:///cn=*,ou=#{ou},cn=users,#{@suffix}")(targetattr="cn || sn || uid || mail || userPassword || nsRole || objectClass") (version 3.0; acl "service-#{ou.gsub(".", "-")}-read-search"; allow (read,search) userdn="ldap:///uid=service,ou=#{ou},cn=applications,#{@suffix}";)
|
||||
EOS
|
||||
|
||||
attrs = {
|
||||
objectClass: ["top", "organizationalUnit"],
|
||||
description: description,
|
||||
ou: ou,
|
||||
aci: aci
|
||||
}
|
||||
|
||||
add_entry dn, attrs, interactive
|
||||
end
|
||||
|
||||
def reset_directory!
|
||||
if Rails.env.production?
|
||||
raise "Resetting the directory not allowed in production"
|
||||
end
|
||||
|
||||
delete_all_entries!
|
||||
|
||||
user_read_aci = <<-EOS
|
||||
(target="ldap:///#{@suffix}")(targetattr="*") (version 3.0; acl "user-read-search-own-attributes"; allow (read,search) userdn="ldap:///self";)
|
||||
EOS
|
||||
|
||||
add_entry @suffix, {
|
||||
dc: "kosmos", objectClass: ["top", "domain"], aci: user_read_aci
|
||||
}, true
|
||||
|
||||
add_entry "cn=users,#{@suffix}", {
|
||||
cn: "users", objectClass: ["top", "organizationalRole"]
|
||||
}, true
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def ldap_client
|
||||
ldap_client ||= Net::LDAP.new host: ldap_config['host'],
|
||||
port: ldap_config['port'],
|
||||
# TODO has to be :simple_tls if TLS is enabled
|
||||
# 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
|
|
@ -2,7 +2,7 @@ class Lndhub
|
|||
attr_accessor :auth_token
|
||||
|
||||
def initialize
|
||||
@base_url = ENV["LNDHUB_API_URL"]
|
||||
@base_url = ENV["LNDHUB_LEGACY_API_URL"]
|
||||
end
|
||||
|
||||
def post(endpoint, payload)
|
||||
|
@ -28,8 +28,13 @@ class Lndhub
|
|||
"Accept" => "application/json",
|
||||
"Authorization" => "Bearer #{auth_token}"
|
||||
})
|
||||
data = JSON.parse(res.body)
|
||||
|
||||
JSON.parse(res.body)
|
||||
if data.is_a?(Hash) && data["error"] && data["message"] == "bad auth"
|
||||
raise "BAD_AUTH"
|
||||
else
|
||||
data
|
||||
end
|
||||
end
|
||||
|
||||
def create(payload)
|
||||
|
@ -42,15 +47,15 @@ class Lndhub
|
|||
self.auth_token
|
||||
end
|
||||
|
||||
def balance(user_token)
|
||||
def balance(user_token=nil)
|
||||
get "balance", user_token || auth_token
|
||||
end
|
||||
|
||||
def gettxs(user_token)
|
||||
def gettxs(user_token=nil)
|
||||
get "gettxs", user_token || auth_token
|
||||
end
|
||||
|
||||
def getuserinvoices(user_token)
|
||||
def getuserinvoices(user_token=nil)
|
||||
get "getuserinvoices", user_token || auth_token
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
class LndhubV2
|
||||
attr_accessor :auth_token
|
||||
|
||||
def initialize
|
||||
@base_url = ENV["LNDHUB_API_URL"]
|
||||
end
|
||||
|
||||
def post(endpoint, payload, options={})
|
||||
headers = { "Content-Type" => "application/json" }
|
||||
if auth_token
|
||||
headers.merge!({ "Authorization" => "Bearer #{auth_token}" })
|
||||
elsif options[:admin_token]
|
||||
headers.merge!({ "Authorization" => "Bearer #{options[:admin_token]}" })
|
||||
end
|
||||
|
||||
res = Faraday.post "#{@base_url}/#{endpoint}", payload.to_json, headers
|
||||
|
||||
if res.status != 200
|
||||
Rails.logger.error "[lndhub] API request failed:"
|
||||
Rails.logger.error res.body
|
||||
#TODO add some kind of exception tracking/notifications
|
||||
end
|
||||
|
||||
JSON.parse(res.body)
|
||||
end
|
||||
|
||||
def get(endpoint, auth_token)
|
||||
res = Faraday.get("#{@base_url}/#{endpoint}", {}, {
|
||||
"Content-Type" => "application/json",
|
||||
"Accept" => "application/json",
|
||||
"Authorization" => "Bearer #{auth_token}"
|
||||
})
|
||||
|
||||
JSON.parse(res.body)
|
||||
end
|
||||
|
||||
def create(payload)
|
||||
post "create", payload
|
||||
end
|
||||
|
||||
def authenticate(user)
|
||||
credentials = post "auth?type=auth", { login: user.ln_login, password: user.ln_password }
|
||||
self.auth_token = credentials["access_token"]
|
||||
self.auth_token
|
||||
end
|
||||
|
||||
def balance(user_token=nil)
|
||||
get "balance", user_token || auth_token
|
||||
end
|
||||
|
||||
def gettxs(user_token)
|
||||
get "gettxs", user_token || auth_token
|
||||
end
|
||||
|
||||
def getuserinvoices(user_token)
|
||||
get "getuserinvoices", user_token || auth_token
|
||||
end
|
||||
|
||||
def addinvoice(payload)
|
||||
invoice = post "addinvoice", {
|
||||
amt: payload[:amount],
|
||||
memo: payload[:memo],
|
||||
description_hash: payload[:description_hash]
|
||||
}
|
||||
|
||||
invoice["payment_request"]
|
||||
end
|
||||
|
||||
#
|
||||
# V2
|
||||
#
|
||||
|
||||
def create_account(payload={})
|
||||
post "v2/users", payload, admin_token: Rails.application.credentials.lndhub[:admin_token]
|
||||
end
|
||||
|
||||
def create_invoice(payload)
|
||||
# Payload: { amount: 1000, description: "", description_hash: "" }
|
||||
post "v2/invoices", payload
|
||||
end
|
||||
end
|
|
@ -1 +1 @@
|
|||
oDf4FcihlyfHQuf9SUwfr+UVA0kXoECtHV3vEwtBp2TktCWkWz7SPbSZ2cLT0+EknOKhuI9xutrs311YDU2EzqZba4fZ0+a6/ohVH4jUbk1XfiHZWBp4zh+9TZ5m5Tp2RxcXpdcWPY38mP4zHWFzobTOR/brLjuemozvh8MiBSPY4NN5NR6rbFo87auK6fvYO8ik/1Qwf6pQMoVDjcTh2983po1RU/gSevUmaYsmTTHcQ5T9O9wMIBc101iZyKhkAZG46a6eNYok8yqRm18AHWr+De2j7LlBaqYSz/BZA385RWhhqoeONArwyo3Az30Bv74VttUSJAPurkRg2wDF9t8A+cvf8CeYkZ6u398JLSJbZZ6YdQS5T4IcrnONRXtp3d/m+yw+XEzpluK3MvFbV02AhZk/xzkGK6xonhaTSh1ek9hXoYrUTBzu8HBzXwKjJMnvrAodldu++/rMwLsgVmFHqXC3dydVogatLev8z6ziuGkmeMAR1d9kzGBHM3FWgsWLD7j0Ug7MTMyNWioI3r6J2QTnxkyJGh3pKBlq8Fb/Q0ypERxOfSZVQQh2gB79RMEDIemdCmN5mCU3ojsxqAAip4v9C1BZMWPtom1sHLYQSd9Bh6i0nncrNEtZXcxe5Z8JCWQolHvvfoIF2rfJh2oXYLxNx5n/1fzaoSqBdLBgvsAMA0ZWfV1wa/5V/DCa9vaJjumzHYKcfCCYbVz9PjN9OUSfwrE3nWZu8Y0awsNgmeRQwI10j2+oYYSBp040I05Vj5FM7nCgHLpdupctwaH2/VlIq83OVI6VlbzxYEay7+R5ANmpiJ+vC466DzLv8LAeFOqh/XeNeOITUm9EzhGSgf98yuDc7vsi3gmc2g7atgQ3gpSje6vEfhigm3ukydaGfA==--IYQBMD+Tar1g+srm--01E5mujYFWvcpT8Qd9HxiA==
|
||||
yEs5CyuAbqphlDWgtw/YQvkPn+EN4ecen2dAjs7zvYErkRRWp99FinGlQIMe6NRkMLLLSIj2BwR/wlscn1kLpIfwGpxfSZ89srK3do6Mb5QogpxdUsnQB8qv5PTGRQFBcjM47s1Q5m0t+OKxGvOnLyKnQp+cVS2KFJMbSzQarW8wIZSz2gKArn9Ttk0kqUHMlJWNY7Yh6xIrrxlEalaTOVzPdtnF7u8Tobminu15eeWHMormMRz4dYSaDc6hUtfpdy1NzOHaeXIU9A9RY/iytxuIQNgcMAlcWbPe//rVk/unH2F8xqSOfed4h/nC08F/qq4z8va3kEXBSdW/G91aIDMu1mo0kX3YNibq8s25C/CfGpzw39ozJ9erTBH7hy6nfmxU6qZuWcTGDj3NOfKe/XIfDcpOjsqkT2IOFARrYodb67q23IuOufraK1/FD4LXu8l0S8/Oi0cqMjtPPs7tS0M1C3DrbmlEzGKETrHpmoKHqjA0rgOmK4ZZM9LeI+l8Z+fDpYcCak9fLGGxnjf+nKiYMSUtm9+1dwycG2lpBV6fbmIKHJWngO2jVGcycODkc525oUaAO4hdPMqrz1AdU3AzYmLJTxW3aZ4uL5NyEJ7TbUBC0HT7h2gEi/tUry4cfD2EsM9bCrCUNuMBrnPqd4r8AvORoqqYIw1IEsP0RgWa2+hfeG1QCjBRPFHQOcqo+W25CelivMe79qI08w0iC8S4hfOQO4QrmMgtd1BhcR+wVpVE3X9EJZi3Hl7z14hXcSic+gkswJMtVZcnJL4rmZ0iEW1mpqUuegsX5vB/4qPxiQyeB80pg8Q33shvUbixzSBkl6znmLSiIffsiDsGOsnuzfl/MUT+JBs3UswNt4tSp7nEwhUjKFHrZHrAJiGCdtIS6yDPGe3HfQv1JkQ+9A8zv88hRmzeIx2JyT/shtIqGo+4ZTJd5cma--Lij/n0+cpstyZD28--FOUhwW3y+0jdaYkKvG2xrg==
|
|
@ -1 +1 @@
|
|||
IIjYiPSeZeMFhH8i8v8akXN4JrtGU+OsMQ8GAao/gVdesggriCBAQ8z+Vd0cmTf1SKYeT3OQDgygEekupr325P4eD9fZ+yi56EA/UMXQXMDVZAvZw7iwvKaOXpqisbWdJnomr1GXrHyR415Ce/Fxft3fgXDwMHJW2u+dDJgpE09uORnB9GXycFwHQmoIdXo=--iQ/Vcm0VcwHgUkwQ--tKHQW/45gM/s/NplqGPaxw==
|
||||
vqH5By5qFLImVjdlWj+7FwGg8APKnr/AEd7WqekG7L0vNA32WGBpwS1uGzs02LIcATRwGj8DyJxiBOB/w9z8cwoO+t6Woi5hAnOSCQwFWKLT0dZq7jgtT8pxK0Yu/Nf91PEFN1rc/8ZFy2KKVpbtMbMPyivT38e/ctBZD/lHrWkndvLXYvFVhqWjUnDOGbhwl/U0RZgqBBjvlm3B0JkQfiN8VXPlCJL2Cd8kd0+MpRCRTgtcxA==--OdVXnDP7OhzJxCsP--+8SI6IFIeXyDxXb+WpqhIQ==
|
|
@ -63,4 +63,7 @@ Rails.application.configure do
|
|||
config.action_mailer.raise_delivery_errors = false
|
||||
# Base URL to be used by email template link helpers
|
||||
config.action_mailer.default_url_options = { host: "localhost:3000", protocol: "http" }
|
||||
|
||||
# Allow requests from any IP
|
||||
config.web_console.whiny_requests = false
|
||||
end
|
||||
|
|
|
@ -26,13 +26,13 @@ authorizations: &AUTHORIZATIONS
|
|||
## Environment
|
||||
|
||||
development:
|
||||
host: 192.168.56.5
|
||||
port: 389
|
||||
host: <%= ENV["LDAP_HOST"] || "localhost" %>
|
||||
port: <%= ENV["LDAP_PORT"] || "389" %>
|
||||
attribute: cn
|
||||
base: ou=kosmos.org,cn=users,dc=kosmos,dc=org
|
||||
base: <%= ENV["LDAP_BASE"] || "ou=kosmos.org,cn=users,dc=kosmos,dc=org" %>
|
||||
admin_user: "cn=Directory Manager"
|
||||
admin_password: localpass
|
||||
# ssl: false
|
||||
admin_password: <%= ENV["LDAP_ADMIN_PASSWORD"] %>
|
||||
ssl: <%= ENV["LDAP_USE_TLS"] || "false" %>
|
||||
# <<: *AUTHORIZATIONS
|
||||
|
||||
test:
|
||||
|
|
31
db/schema.rb
31
db/schema.rb
|
@ -2,25 +2,24 @@
|
|||
# of editing this file, please use the migrations feature of Active Record to
|
||||
# incrementally modify your database, and then regenerate this schema definition.
|
||||
#
|
||||
# This file is the source Rails uses to define your schema when running `rails
|
||||
# db:schema:load`. When creating a new database, `rails db:schema:load` tends to
|
||||
# This file is the source Rails uses to define your schema when running `bin/rails
|
||||
# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
|
||||
# be faster and is potentially less error prone than running all of your
|
||||
# migrations from scratch. Old migrations may fail to apply correctly if those
|
||||
# migrations use external dependencies or application code.
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 2021_11_20_010540) do
|
||||
|
||||
ActiveRecord::Schema[7.0].define(version: 2021_11_20_010540) do
|
||||
create_table "donations", force: :cascade do |t|
|
||||
t.integer "user_id"
|
||||
t.integer "amount_sats"
|
||||
t.integer "amount_eur"
|
||||
t.integer "amount_usd"
|
||||
t.string "public_name"
|
||||
t.datetime "created_at", precision: 6, null: false
|
||||
t.datetime "updated_at", precision: 6, null: false
|
||||
t.datetime "paid_at"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.datetime "paid_at", precision: nil
|
||||
t.index ["user_id"], name: "index_donations_on_user_id"
|
||||
end
|
||||
|
||||
|
@ -28,22 +27,24 @@ ActiveRecord::Schema.define(version: 2021_11_20_010540) do
|
|||
t.string "token"
|
||||
t.integer "user_id"
|
||||
t.integer "invited_user_id"
|
||||
t.datetime "used_at"
|
||||
t.datetime "created_at", precision: 6, null: false
|
||||
t.datetime "updated_at", precision: 6, null: false
|
||||
t.datetime "used_at", precision: nil
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["invited_user_id"], name: "index_invitations_on_invited_user_id"
|
||||
t.index ["user_id"], name: "index_invitations_on_user_id"
|
||||
end
|
||||
|
||||
create_table "users", force: :cascade do |t|
|
||||
t.string "cn"
|
||||
t.string "ou"
|
||||
t.datetime "created_at", precision: 6, null: false
|
||||
t.datetime "updated_at", precision: 6, null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.string "email", default: "", null: false
|
||||
t.string "reset_password_token"
|
||||
t.datetime "reset_password_sent_at"
|
||||
t.datetime "reset_password_sent_at", precision: nil
|
||||
t.string "confirmation_token"
|
||||
t.datetime "confirmed_at"
|
||||
t.datetime "confirmation_sent_at"
|
||||
t.datetime "confirmed_at", precision: nil
|
||||
t.datetime "confirmation_sent_at", precision: nil
|
||||
t.string "unconfirmed_email"
|
||||
t.text "ln_login_ciphertext"
|
||||
t.text "ln_password_ciphertext"
|
||||
|
|
29
db/seeds.rb
29
db/seeds.rb
|
@ -1,7 +1,22 @@
|
|||
# This file should contain all the record creation needed to seed the database with its default values.
|
||||
# The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup).
|
||||
#
|
||||
# Examples:
|
||||
#
|
||||
# movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }])
|
||||
# Character.create(name: 'Luke', movie: movies.first)
|
||||
require 'sidekiq/testing'
|
||||
|
||||
ldap = LdapService.new
|
||||
|
||||
Sidekiq::Testing.inline! do
|
||||
CreateAccount.call(
|
||||
username: "admin", domain: "kosmos.org", email: "admin@example.com",
|
||||
password: "admin is admin", confirmed: true
|
||||
)
|
||||
|
||||
ldap.add_attribute "cn=admin,ou=kosmos.org,cn=users,dc=kosmos,dc=org", :admin, "true"
|
||||
|
||||
5.times do |n|
|
||||
username = Faker::Name.unique.first_name.downcase
|
||||
email = Faker::Internet.unique.email
|
||||
|
||||
CreateAccount.call(
|
||||
username: username, domain: "kosmos.org", email: email,
|
||||
password: "user is user", confirmed: true
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
services:
|
||||
ldap:
|
||||
image: 4teamwork/389ds:latest
|
||||
volumes:
|
||||
- ./tmp/389ds:/data
|
||||
ports:
|
||||
- "389:3389"
|
||||
environment:
|
||||
DS_DM_PASSWORD: passthebutter
|
||||
SUFFIX_NAME: "dc=kosmos,dc=org"
|
||||
# phpldapadmin:
|
||||
# image: osixia/phpldapadmin:0.9.0
|
||||
# ports:
|
||||
# - "8389:80"
|
||||
# environment:
|
||||
# PHPLDAPADMIN_HTTPS: false
|
||||
# PHPLDAPADMIN_LDAP_HOSTS: "#PYTHON2BASH:[{'ldap': [{'server': [{'tls': False}, {'port': 3389}]}, {'login': [{'bind_id': 'cn=Directory Manager'}, {'bind_pass': 'passthebutter'}]}]}]"
|
||||
# PHPLDAPADMIN_LDAP_CLIENT_TLS: false
|
||||
# web:
|
||||
# build: .
|
||||
# tty: true
|
||||
# command: bash -c "sleep 5 && rm -f tmp/pids/server.pid && bin/dev"
|
||||
# volumes:
|
||||
# - .:/akkounts
|
||||
# ports:
|
||||
# - "3000:3000"
|
||||
# environment:
|
||||
# RAILS_ENV: development
|
||||
# LDAP_HOST: ldap
|
||||
# LDAP_PORT: 3389
|
||||
# LDAP_ADMIN_PASSWORD: passthebutter
|
||||
# LDAP_USE_TLS: "false"
|
||||
# depends_on:
|
||||
# - ldap
|
|
@ -0,0 +1,8 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Remove a potentially pre-existing server.pid for Rails.
|
||||
rm -f /myapp/tmp/pids/server.pid
|
||||
|
||||
# Then exec the container's main process (what's set as CMD in the Dockerfile).
|
||||
exec "$@"
|
|
@ -0,0 +1,28 @@
|
|||
namespace :ldap do
|
||||
desc "Reset the LDAP directory and set up base entries and default org"
|
||||
task setup: :environment do |t, args|
|
||||
ldap = LdapService.new
|
||||
|
||||
ldap.delete_entry "cn=admin_role,ou=kosmos.org,cn=users,dc=kosmos,dc=org", true
|
||||
|
||||
# Delete all existing entries and re-add base entries
|
||||
ldap.reset_directory!
|
||||
|
||||
ldap.add_organization "kosmos.org", "Kosmos", true
|
||||
|
||||
# add admin role
|
||||
ldap.add_entry "cn=admin_role,ou=kosmos.org,cn=users,dc=kosmos,dc=org", {
|
||||
objectClass: %w{top LDAPsubentry nsRoleDefinition nsComplexRoleDefinition nsFilteredRoleDefinition},
|
||||
cn: "admin_role",
|
||||
nsRoleFilter: "(&(objectclass=person)(admin=true))",
|
||||
description: "filtered role for admins"
|
||||
}, true
|
||||
end
|
||||
|
||||
desc "List user domains/organizations"
|
||||
task list_organizations: :environment do |t, args|
|
||||
ldap = LdapService.new
|
||||
orgs = ldap.fetch_organizations
|
||||
puts orgs.inspect
|
||||
end
|
||||
end
|
|
@ -21,4 +21,31 @@ namespace :lndhub do
|
|||
end
|
||||
puts "--\nSum of user balances: #{sum} sats"
|
||||
end
|
||||
|
||||
desc "Migrate existing accounts to lndhub.go"
|
||||
task :migrate => :environment do |t, args|
|
||||
# user = User.find_by cn: "jimmy"
|
||||
User.all.each do |user|
|
||||
puts "Migrating #{user.cn}"
|
||||
puts "Creating account..."
|
||||
lndhub_v2 = LndhubV2.new
|
||||
res = lndhub_v2.create_account login: user.ln_login, password: user.ln_password
|
||||
puts res.inspect
|
||||
|
||||
lndhub = Lndhub.new
|
||||
lndhub.authenticate(user)
|
||||
data = lndhub.balance
|
||||
balance = data["BTC"]["AvailableBalance"] rescue 0
|
||||
|
||||
if balance > 0
|
||||
lndhub_v2.authenticate(user)
|
||||
desc = "Balance migration from old Kosmos Lightning back-end"
|
||||
res = lndhub_v2.create_invoice amount: balance, description: desc
|
||||
puts "Payment request for #{user.cn} (#{balance} sats):"
|
||||
puts res["payment_request"]
|
||||
end
|
||||
|
||||
puts "---"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
14
package.json
14
package.json
|
@ -2,14 +2,14 @@
|
|||
"name": "akkounts",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@tailwindcss/forms": "^0.4.0",
|
||||
"autoprefixer": "^10.4.2",
|
||||
"postcss": "^8.4.6",
|
||||
"@tailwindcss/forms": "^0.5.3",
|
||||
"autoprefixer": "^10.4.13",
|
||||
"postcss": "^8.4.19",
|
||||
"postcss-flexbugs-fixes": "^5.0.2",
|
||||
"postcss-import": "^14.0.2",
|
||||
"postcss-nested": "^5.0.6",
|
||||
"postcss-preset-env": "^7.3.1",
|
||||
"tailwindcss": "^3.0.22"
|
||||
"postcss-import": "^15.0.1",
|
||||
"postcss-nested": "^6.0.0",
|
||||
"postcss-preset-env": "^7.8.3",
|
||||
"tailwindcss": "^3.2.4"
|
||||
},
|
||||
"version": "0.4.0",
|
||||
"scripts": {
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
require 'rails_helper'
|
||||
require 'webmock/rspec'
|
||||
|
||||
RSpec.describe CreateLndhubWalletJob, type: :job do
|
||||
RSpec.describe CreateLndhubAccountJob, type: :job do
|
||||
let(:user) { create :user, cn: "willherschel", ou: "kosmos.org" }
|
||||
|
||||
subject(:job) { described_class.perform_later(user) }
|
||||
|
||||
before do
|
||||
stub_request(:post, "http://localhost:3023/create")
|
||||
stub_request(:post, "http://localhost:3026/v2/users")
|
||||
.to_return(status: 200, headers: {},
|
||||
body: { login: "abc123", password: "def456" }.to_json)
|
||||
end
|
||||
|
@ -15,8 +15,8 @@ RSpec.describe CreateLndhubWalletJob, type: :job do
|
|||
it "creates a new LndHub account" do
|
||||
perform_enqueued_jobs { job }
|
||||
|
||||
expect(WebMock).to have_requested(:post, "http://localhost:3023/create")
|
||||
.with { |req| req.body == '{"partnerid":"kosmos.org","accounttype":"user"}' }
|
||||
expect(WebMock).to have_requested(:post, "http://localhost:3026/v2/users")
|
||||
.with { |req| req.body == '{}' }
|
||||
|
||||
user.reload
|
||||
expect(user.ln_login).to eq("abc123")
|
|
@ -93,7 +93,7 @@ RSpec.describe CreateAccount, type: :model do
|
|||
end
|
||||
end
|
||||
|
||||
describe "#create_lndhub_wallet" do
|
||||
describe "#create_lndhub_account" do
|
||||
include ActiveJob::TestHelper
|
||||
|
||||
let(:service) { CreateAccount.new(
|
||||
|
@ -102,8 +102,8 @@ RSpec.describe CreateAccount, type: :model do
|
|||
)}
|
||||
let(:new_user) { create :user, cn: "halfinney", ou: "kosmos.org" }
|
||||
|
||||
it "enqueues a job to create an LndHub wallet" do
|
||||
service.send(:create_lndhub_wallet, new_user)
|
||||
it "enqueues a job to create an LndHub account" do
|
||||
service.send(:create_lndhub_account, new_user)
|
||||
|
||||
expect(enqueued_jobs.size).to eq(1)
|
||||
|
||||
|
|
Loading…
Reference in New Issue