From 9d8e26eb30cfef97885208b4ec5392ab65267934 Mon Sep 17 00:00:00 2001 From: Jorai Geertsema Date: Sat, 8 Feb 2025 00:13:29 +0100 Subject: [PATCH 1/5] intial commit --- Gemfile | 2 - app/controllers/v1/users_controller.rb | 9 +-- app/models/user.rb | 4 - app/models/webdav/addressbook.rb | 46 ----------- app/models/webdav/contact.rb | 79 ------------------ app/models/webdav/user.rb | 23 ------ app/policies/user_policy.rb | 4 - app/resources/v1/user_resource.rb | 4 +- config/routes.rb | 21 ----- config/routes/contact_sync_handler.rb | 55 ------------- docker-compose.yml | 2 +- spec/factories/users.rb | 2 - spec/models/user_spec.rb | 8 -- spec/models/webdav/addressbook_spec.rb | 73 ----------------- spec/models/webdav/contact_spec.rb | 71 ---------------- spec/models/webdav/user_spec.rb | 24 ------ .../users_controller/activate_webdav_spec.rb | 26 ------ .../requests/v1/users_controller/show_spec.rb | 2 +- .../v1/webdav/addressbook_collection_spec.rb | 71 ---------------- spec/requests/v1/webdav/addressbook_spec.rb | 80 ------------------- spec/requests/v1/webdav/contact_spec.rb | 66 --------------- spec/requests/v1/webdav/principal_spec.rb | 66 --------------- spec/resources/v1/user_resource_spec.rb | 2 +- 23 files changed, 6 insertions(+), 734 deletions(-) delete mode 100644 app/models/webdav/addressbook.rb delete mode 100644 app/models/webdav/contact.rb delete mode 100644 app/models/webdav/user.rb delete mode 100644 config/routes/contact_sync_handler.rb delete mode 100644 spec/models/webdav/addressbook_spec.rb delete mode 100644 spec/models/webdav/contact_spec.rb delete mode 100644 spec/models/webdav/user_spec.rb delete mode 100644 spec/requests/v1/users_controller/activate_webdav_spec.rb delete mode 100644 spec/requests/v1/webdav/addressbook_collection_spec.rb delete mode 100644 spec/requests/v1/webdav/addressbook_spec.rb delete mode 100644 spec/requests/v1/webdav/contact_spec.rb delete mode 100644 spec/requests/v1/webdav/principal_spec.rb diff --git a/Gemfile b/Gemfile index 95aa6455..3f8ccdb6 100644 --- a/Gemfile +++ b/Gemfile @@ -1,7 +1,6 @@ source 'https://rubygems.org' gem 'active_model_otp', git: 'https://github.com/heapsource/active_model_otp.git', ref: '6ed9927' -gem 'dav4rack', git: 'https://github.com/csvalpha/dav4rack.git', ref: '8541e53' gem 'bcrypt', '~> 3.1', '>= 3.1.20' gem 'bootsnap', '~> 1.18', '>= 1.18.4' @@ -10,7 +9,6 @@ gem 'carrierwave-base64', '~> 2.11' gem 'carrierwave-bombshelter', '~> 0.2', '>= 0.2.2' gem 'case_transform', '~> 0.2' gem 'counter_culture', '~> 3.8', '>= 3.8.2' -gem 'dav4rack_ext', '~> 1.0' gem 'doorkeeper', '~> 5.8', '>= 5.8.1' gem 'doorkeeper-i18n', '~> 5.2', '>= 5.2.7' gem 'exifr', '~> 1.4' diff --git a/app/controllers/v1/users_controller.rb b/app/controllers/v1/users_controller.rb index 2b208420..ce4c23e0 100644 --- a/app/controllers/v1/users_controller.rb +++ b/app/controllers/v1/users_controller.rb @@ -4,7 +4,7 @@ class V1::UsersController < V1::ApplicationController # rubocop:disable Metrics/ get_related_resource] before_action :set_model, only: %i[update archive activate_account resend_activation_mail generate_otp_secret - activate_otp activate_webdav] + activate_otp] def update password = params.dig('data', 'attributes', 'password') @@ -77,13 +77,6 @@ def activate_otp head :no_content end - def activate_webdav - authorize @model - @model.generate_webdav_secret_key - @model.save - head :no_content - end - def nextcloud render json: { id: current_user.id, displayName: current_user.full_name, diff --git a/app/models/user.rb b/app/models/user.rb index ac38cfc1..8c4fb9f5 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -179,10 +179,6 @@ def self.valid_csv_attributes column_names.map(&:to_sym) + %i[full_name avatar_url] end - def generate_webdav_secret_key - self.webdav_secret_key = SecureRandom.hex(32) - end - def to_ical # rubocop:disable Metrics/AbcSize return unless birthday diff --git a/app/models/webdav/addressbook.rb b/app/models/webdav/addressbook.rb deleted file mode 100644 index a8e74528..00000000 --- a/app/models/webdav/addressbook.rb +++ /dev/null @@ -1,46 +0,0 @@ -module Webdav - class Addressbook - def initialize(group) - @group = group - end - - def name - @group.name - end - - def path - @group.id - end - - def contacts - @contacts ||= @group.active_users.contactsync_users.collect { |u| Webdav::Contact.new(u) } - end - - def ctag - updated_at.to_i - end - - def find_contact(uid) - contacts.detect { |c| c.uid == uid } - end - - def find_contacts(ids) - ids.each_with_object({}) do |(href, path), ret| - uid = File.basename(path, '.vcf') - ret[href] = contacts.detect { |c| c.uid == uid } - end - end - - def create_contact(*) - true # no-op - end - - def updated_at - @group.active_users.maximum(:updated_at).to_i - end - - def created_at - @group.updated_at.to_i - end - end -end diff --git a/app/models/webdav/contact.rb b/app/models/webdav/contact.rb deleted file mode 100644 index 676b1f4d..00000000 --- a/app/models/webdav/contact.rb +++ /dev/null @@ -1,79 +0,0 @@ -module Webdav - class Contact - def initialize(user) - @user = user - end - - def uid - @user.id.to_s - end - - def path - uid - end - - def update_from_vcard(*) - true # no op - end - - def save(*) - true # no-op - end - - def destroy - true # no-op - end - - def etag - updated_at - end - - def created_at - @user.created_at.to_i - end - - def updated_at - @user.updated_at.to_i - end - - def vcard - Struct::Vcard.new(self.class.user_to_vcard(@user)) - end - - def self.user_to_vcard(user) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize - Vpim::Vcard::Maker.make2 do |maker| - maker.add_name do |name| - name.given = user.first_name - name.family = user.last_name - name.additional = user.last_name_prefix if user.last_name_prefix - end - maker.nickname = user.nickname - maker.birthday = user.birthday if user.birthday - maker.add_addr do |address| - address.location = 'home' - address.street = user.address - address.locality = user.city - address.postalcode = user.postcode - end - maker.add_email(user.email) - if user.phone_number - maker.add_tel(user.phone_number) { |telephone| telephone.capability = %w[voice cell] } - end - maker.add_field(Vpim::DirectoryInfo::Field.create('REV', Time.zone.now)) - maker.add_field(Vpim::DirectoryInfo::Field.create('PRODID', 'C.S.V. Alpha')) - end - end - end - - # The carddav library uses 2 methods to get the vcard representation: - # contact.vcard.vcard and contact.vcard.to_s - Struct.new('Vcard', :card) do - def vcard - to_s - end - - def to_s(*) - card.to_s - end - end -end diff --git a/app/models/webdav/user.rb b/app/models/webdav/user.rb deleted file mode 100644 index cd6b00a9..00000000 --- a/app/models/webdav/user.rb +++ /dev/null @@ -1,23 +0,0 @@ -module Webdav - class User - attr_accessor :current_contact - - def initialize(user, book_id) - @user = user - @book_id = book_id - end - - def all_addressbooks - @user.active_groups.map do |group| - Webdav::Addressbook.new(group) - end - end - - def current_addressbook - group = @user.active_groups.find(@book_id) - return unless group - - @current_addressbook = Webdav::Addressbook.new(group) - end - end -end diff --git a/app/policies/user_policy.rb b/app/policies/user_policy.rb index 147b411b..1400d321 100644 --- a/app/policies/user_policy.rb +++ b/app/policies/user_policy.rb @@ -41,10 +41,6 @@ def activate_otp? me? end - def activate_webdav? - me? - end - def batch_import? create? end diff --git a/app/resources/v1/user_resource.rb b/app/resources/v1/user_resource.rb index bef3359f..9a69e573 100644 --- a/app/resources/v1/user_resource.rb +++ b/app/resources/v1/user_resource.rb @@ -4,7 +4,7 @@ class V1::UserResource < V1::ApplicationResource # rubocop:disable Metrics/Class :ifes_data_sharing_preference, :info_in_almanak, :almanak_subscription_preference, :digtus_subscription_preference, :email, :birthday, :address, :postcode, :city, :phone_number, :food_preferences, :vegetarian, :study, :start_study, - :picture_publication_preference, :ical_secret_key, :webdav_secret_key, + :picture_publication_preference, :ical_secret_key, :password, :avatar, :avatar_url, :avatar_thumb_url, :user_details_sharing_preference, :allow_tomato_sharing @@ -52,7 +52,7 @@ def fetchable_fields # Relationships allowed_keys += %i[groups active_groups memberships mail_aliases mandates group_mail_aliases permissions photos user_permissions] - allowed_keys += %i[ical_secret_key webdav_secret_key] if me? + allowed_keys += %i[ical_secret_key] if me? if update_or_me? allowed_keys += %i[login_enabled otp_required activated_at emergency_contact emergency_number ifes_data_sharing_preference info_in_almanak diff --git a/config/routes.rb b/config/routes.rb index 03c964d5..7ecff655 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -68,7 +68,6 @@ post :resend_activation_mail post :generate_otp_secret post :activate_otp - post :activate_webdav end end get 'users/me/nextcloud', to: 'users#nextcloud' @@ -111,26 +110,6 @@ get 'coffee', to: 'coffee#index' get 'ical/activities', to: 'v1/activities#ical' - namespace :webdav do - match ':user_id/:key/contacts', via: :all, to: ContactSyncHandler.new( - resource_class: DAV4Rack::Carddav::PrincipalResource, - books_collection: '/books/' - ) - - match ':user_id/:key/contacts/books/', via: :all, to: ContactSyncHandler.new( - resource_class: DAV4Rack::Carddav::AddressbookCollectionResource - ) - - match ':user_id/:key/contacts/books/:book_id', via: :all, to: ContactSyncHandler.new( - resource_class: DAV4Rack::Carddav::AddressbookResource - ) - - match ':user_id/:key/contacts/books/:book_id/:contact_id(.vcf)', - via: :all, to: ContactSyncHandler.new( - resource_class: DAV4Rack::Carddav::ContactResource - ) - end - require 'sidekiq/web' require 'sidekiq-scheduler/web' diff --git a/config/routes/contact_sync_handler.rb b/config/routes/contact_sync_handler.rb deleted file mode 100644 index 86e9fc98..00000000 --- a/config/routes/contact_sync_handler.rb +++ /dev/null @@ -1,55 +0,0 @@ -class ContactSyncHandler < DAV4RackExt::Handler - def initialize(options = {}) # rubocop:disable Style/OptionHash - super(default_options.merge(options)) - end - - def call(env) - super(env) - rescue ActiveRecord::RecordNotFound - Rack::Response.new([], 404).finish - end - - def default_options - { - dav_extensions: DAV4Rack::Carddav::DAV_EXTENSIONS, - controller_class: DAV4Rack::Carddav::Controller, - logger: ::Logger.new('/dev/null'), - always_include_dav_header: true, - pretty_xml: true, - root_uri_path: ->(env) { root_uri_path(env) }, - current_user: ->(env) { current_webdav_user(env) } - } - end - - def root_uri_path(env) - path = env['PATH_INFO'] - path[0...(path.index('/contacts') + 9)] - end - - def current_webdav_user(env) - params = request_params(env) - user = user(params[:user_id], params[:key]) - webdav_user = Webdav::User.new(user, params[:book_id]) - if params[:contact_id] - webdav_user.current_contact = - webdav_user.current_addressbook.find_contact(params[:contact_id]) - end - webdav_user - end - - def request_params(env) - { - user_id: env['action_dispatch.request.path_parameters'][:user_id], - key: env['action_dispatch.request.path_parameters'][:key], - contact_id: env['action_dispatch.request.path_parameters'][:contact_id], - book_id: env['action_dispatch.request.path_parameters'][:book_id] - } - end - - def user(user_id, key) - user = User.activated.login_enabled.find_by(id: user_id, webdav_secret_key: key) - raise ActiveRecord::RecordNotFound unless user - - user - end -end diff --git a/docker-compose.yml b/docker-compose.yml index 5de27372..8a9d8b7b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -38,7 +38,7 @@ services: - ./log:/app/log labels: - traefik.enable=true - - traefik.http.routers.amber-api-staging.rule=Host(`$HOST`) && PathPrefix(`/api`, `/uploads`, `/sidekiq`, `/webdav`, `/ical`) + - traefik.http.routers.amber-api-staging.rule=Host(`$HOST`) && PathPrefix(`/api`, `/uploads`, `/sidekiq`, `/ical`) - traefik.http.routers.amber-api-staging.middlewares=amber-api-strip@file - traefik.http.routers.amber-api-staging.tls.certresolver=default diff --git a/spec/factories/users.rb b/spec/factories/users.rb index 96f8a32e..fc0d967f 100644 --- a/spec/factories/users.rb +++ b/spec/factories/users.rb @@ -32,8 +32,6 @@ otp_required { false } login_enabled { true } - trait(:webdav_enabled) { webdav_secret_key { SecureRandom.hex(32) } } - transient do user_permission_list { [] } groups { [] } diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index addb0295..c492123c 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -317,14 +317,6 @@ end end - describe '.contactsync_users' do - it do - expect { create(:user, webdav_secret_key: SecureRandom.hex(32)) }.to( - change { described_class.contactsync_users.count }.by(1) - ) - end - end - describe '.login_enabled' do it do expect { create(:user, login_enabled: true) }.to( diff --git a/spec/models/webdav/addressbook_spec.rb b/spec/models/webdav/addressbook_spec.rb deleted file mode 100644 index 01f2e2a9..00000000 --- a/spec/models/webdav/addressbook_spec.rb +++ /dev/null @@ -1,73 +0,0 @@ -require 'rails_helper' - -RSpec.describe Webdav::Addressbook, type: :model do - let(:users) do - [ - create(:user, :webdav_enabled), - create(:user), - create(:user, :webdav_enabled) - ] - end - let(:group) { create(:group, users:) } - - subject(:addressbook) { described_class.new(group) } - - describe '#name' do - it { expect(addressbook.name).to eq(group.name) } - end - - describe '#path' do - it { expect(addressbook.path).to eq(group.id) } - end - - describe '#contacts' do - it { expect(addressbook.contacts.size).to eq(2) } - - it { - expect(addressbook.contacts.collect(&:uid)).to contain_exactly(users[0].id.to_s, - users[2].id.to_s) - } - end - - describe '#ctag' do - it { expect(addressbook.ctag).to eq(group.updated_at.to_i) } - end - - describe '#find_contact' do - it { expect(addressbook.find_contact(users[2].id.to_s)).not_to be_nil } - it { expect(addressbook.find_contact(users[2].id.to_s).uid).to eq(users[2].id.to_s) } - it { expect(addressbook.find_contact(users[1].id.to_s)).to be_nil } - it { expect(addressbook.find_contact((users[2].id + 1).to_s)).to be_nil } - end - - describe '#find_contacts' do - let(:uid) { users[0].id.to_s } - let(:href) { "/webdav/1/secret/contacts/books/leden/#{uid}" } - - it do - expect(addressbook.find_contacts(href => uid)) - .to eq(href => addressbook.contacts.find { |c| c.uid == uid }) - end - end - - describe '#create_contact' do - let(:new_contact) { Webdav::Contact.new(build_stubbed(:user)) } - - before { users } - - it do - expect { addressbook.create_contact(new_contact) } - .not_to(change { addressbook.contacts.count }) - end - - it { expect { addressbook.create_contact(new_contact) }.not_to(change(User, :count)) } - end - - describe '#updated_at' do - it { expect(addressbook.updated_at).to eq([users[0], users[2]].map(&:updated_at).max.to_i) } - end - - describe '#created_at' do - it { expect(addressbook.created_at).to eq(group.created_at.to_i) } - end -end diff --git a/spec/models/webdav/contact_spec.rb b/spec/models/webdav/contact_spec.rb deleted file mode 100644 index e63a1304..00000000 --- a/spec/models/webdav/contact_spec.rb +++ /dev/null @@ -1,71 +0,0 @@ -require 'rails_helper' - -RSpec.describe Webdav::Contact, type: :model do - let(:user) { build_stubbed(:user) } - - subject(:contact) { described_class.new(user) } - - describe '#uid' do - it { expect(contact.uid).to eq(user.id.to_s) } - end - - describe '#path' do - it { expect(contact.path).to eq(user.id.to_s) } - end - - describe '#update_from_vcard()' do - let(:other_user) { build_stubbed(:user) } - let(:other_vcard) { described_class.user_to_vcard(other_user) } - - it { expect { contact.update_from_vcard(other_vcard) }.not_to(change(user, :first_name)) } - end - - describe '#save' do - it { expect { contact.save(nil) }.not_to(change(user, :updated_at)) } - end - - describe '#destroy' do - it { expect { contact.destroy }.not_to(change(User, :count)) } - end - - describe '#etag' do - it { expect(contact.etag).to eq(user.updated_at.to_i) } - end - - describe '#created_at' do - it { expect(contact.created_at).to eq(user.created_at.to_i) } - end - - describe '#updated_at' do - it { expect(contact.updated_at).to eq(user.updated_at.to_i) } - end - - describe '#vcard' do - let(:vcard) { described_class.user_to_vcard(user) } - - it { expect(contact.vcard).not_to be_nil } - it { expect(contact.vcard.vcard).to eq(vcard.to_s) } - it { expect(contact.vcard.to_s).to eq(vcard.to_s) } - end - - describe '#user_to_vcard' do - let(:time_now) { Time.zone.now } - - subject(:vcard) { described_class.user_to_vcard(user) } - - it { allow(Time.zone).to receive(:now).and_return(time_now) } - it { expect(vcard.name.given).to eq(user.first_name) } - it { expect(vcard.name.family).to eq(user.last_name) } - it { expect(vcard.name.additional).to eq(user.last_name_prefix || '') } - it { expect(vcard.birthday).to eq(user.birthday) } - it { expect(vcard.address.location).to eq(['home']) } - it { expect(vcard.address.street).to eq(user.address) } - it { expect(vcard.address.locality).to eq(user.city) } - it { expect(vcard.address.postalcode).to eq(user.postcode) } - it { expect(vcard.email).to eq(user.email) } - it { expect(vcard.telephones.first).to eq(user.phone_number) } - # Testing REV doesnt work on CI, this gives an timing issue - # it { expect(Time.parse(vcard.field('REV').value).to_i).to eq(time_now.to_i) } - it { expect(vcard.field('PRODID').value).to eq('C.S.V. Alpha') } - end -end diff --git a/spec/models/webdav/user_spec.rb b/spec/models/webdav/user_spec.rb deleted file mode 100644 index 3f7e1cea..00000000 --- a/spec/models/webdav/user_spec.rb +++ /dev/null @@ -1,24 +0,0 @@ -require 'rails_helper' - -RSpec.describe Webdav::User, type: :model do - let(:user) { create(:user) } - let(:group) { create(:group, users: [user]) } - - subject(:webdav_user) { described_class.new(user, group.id) } - - describe '#current_addressbook' do - it { expect(webdav_user.current_addressbook.name).to eq(group.name) } - end - - describe '#all_addressbooks' do - it { expect(webdav_user.all_addressbooks.size).to eq(user.active_groups.size) } - it { expect(webdav_user.all_addressbooks[0].name).to eq(group.name) } - end - - describe '#current_contact' do - before { webdav_user.current_contact = Webdav::Contact.new(user) } - - it { expect(webdav_user.current_contact).not_to be_nil } - it { expect(webdav_user.current_contact.uid).to eq(user.id.to_s) } - end -end diff --git a/spec/requests/v1/users_controller/activate_webdav_spec.rb b/spec/requests/v1/users_controller/activate_webdav_spec.rb deleted file mode 100644 index bb4de381..00000000 --- a/spec/requests/v1/users_controller/activate_webdav_spec.rb +++ /dev/null @@ -1,26 +0,0 @@ -require 'rails_helper' - -describe V1::UsersController do - describe 'GET /users/:id/activate_webdav', version: 1 do - let(:record) { create(:user) } - let(:record_url) { "/v1/users/#{record.id}/activate_webdav" } - - subject(:request) { post(record_url) } - - it_behaves_like '401 Unauthorized' - - context 'when authenticated' do - include_context 'when authenticated' - it_behaves_like '403 Forbidden' - - context 'when requesting as user itself' do - include_context 'when authenticated' do - let(:user) { record } - end - - it_behaves_like '204 No Content' - it { expect { request && user.reload }.to(change(user, :webdav_secret_key)) } - end - end - end -end diff --git a/spec/requests/v1/users_controller/show_spec.rb b/spec/requests/v1/users_controller/show_spec.rb index cbe9a7b8..6cbdccab 100644 --- a/spec/requests/v1/users_controller/show_spec.rb +++ b/spec/requests/v1/users_controller/show_spec.rb @@ -98,7 +98,7 @@ authenticated_attributes = %w[ email birthday address postcode phone_number study - food_preferences vegetarian start_study ical_secret_key webdav_secret_key + food_preferences vegetarian start_study ical_secret_key city picture_publication_preference info_in_almanak almanak_subscription_preference digtus_subscription_preference emergency_contact emergency_number ifes_data_sharing_preference diff --git a/spec/requests/v1/webdav/addressbook_collection_spec.rb b/spec/requests/v1/webdav/addressbook_collection_spec.rb deleted file mode 100644 index a46426a6..00000000 --- a/spec/requests/v1/webdav/addressbook_collection_spec.rb +++ /dev/null @@ -1,71 +0,0 @@ -require 'rails_helper' - -describe 'DAV4Rack::Carddav::Controller for DAV4Rack::Carddav::AddressbookCollectionResource' do - describe 'PROPFIND /webdav/:user_id/:key/contacts/books', version: 1 do - let(:users) { create_list(:user, 4, :webdav_enabled, activated_at: Time.zone.now) } - let(:user) { users.first } - let(:group) do - create(:group, users:) - end - - before { group } - - context 'when requesting resourcetype and displayname' do - let(:request_data) do - ' - - ' - end - - context 'when with invalid secret' do - let(:request_url) { "/webdav/#{user.id}/invalidsecret/contacts/books" } - - subject(:request) do - current_session.request(request_url, method: 'PROPFIND', params: request_data) - end - - it_behaves_like '404 Not Found' - end - - context 'when with valid secret' do - let(:request_url) { "/webdav/#{user.id}/#{user.webdav_secret_key}/contacts/books" } - let(:xml) { Hash.from_xml(request.body) } - let(:responses) { xml['multistatus']['response'] } - - subject(:request) do - current_session.request(request_url, method: 'PROPFIND', params: request_data) - end - - # For an example response see https://github.com/csvalpha/amber-api/wiki/CardDAV-explained-with-examples - it_behaves_like '207 Multistatus' - it { expect(responses.length).to eq(6) } - # Second response is the addressbook - - it { - expect(responses[1]['href']) - .to eq("/webdav/#{user.id}/#{user.webdav_secret_key}/contacts/books/#{group.id}/") - } - - it { - expect(responses[1]['propstat']['prop']['resourcetype'].keys) - .to contain_exactly('collection', 'addressbook') - } - - it { expect(responses[1]['propstat']['prop']['displayname']).to eq group.name } - # third to fifth responses are members - - it { - expect(responses[2..5].map { |r| r['href'] }) - .to match_array(group.users.map do |u| - "/webdav/#{user.id}/#{user.webdav_secret_key}/contacts/books/#{group.id}/#{u.id}" - end) - } - - it { - expect(responses[2..5].map { |r| r['propstat']['prop']['displayname'] }) - .to match_array(group.users.map { |u| u.id.to_s }) - } - end - end - end -end diff --git a/spec/requests/v1/webdav/addressbook_spec.rb b/spec/requests/v1/webdav/addressbook_spec.rb deleted file mode 100644 index 7c76121d..00000000 --- a/spec/requests/v1/webdav/addressbook_spec.rb +++ /dev/null @@ -1,80 +0,0 @@ -require 'rails_helper' - -describe 'DAV4Rack::Carddav::Controller for DAV4Rack::Carddav::AddressbookResource' do - describe 'PROPFIND /webdav/:user_id/:key/contacts/books/:group_id', version: 1 do - let(:users) { create_list(:user, 4, :webdav_enabled, activated_at: Time.zone.now) } - let(:user) { users.first } - let(:group) { create(:group, users:) } - let(:not_member_group) do - create(:group, users: create_list(:user, 3)) - end - - before { group && not_member_group } - - context 'when requesting props' do - let(:request_data) do - ' - - - - - - - - ' - end - - context 'when with invalid secret' do - let(:request_url) { "/webdav/#{user.id}/invalidsecret/contacts/books/#{group.id}" } - - subject(:request) do - current_session.request(request_url, method: 'PROPFIND', params: request_data) - end - - it_behaves_like '404 Not Found' - end - - context 'when with valid secret' do - let(:request_url) do - "/webdav/#{user.id}/#{user.webdav_secret_key}/contacts/books/#{group.id}" - end - let(:xml) { Hash.from_xml(request.body) } - let(:responses) { xml['multistatus']['response'] } - - subject(:request) do - current_session.request(request_url, method: 'PROPFIND', params: request_data) - end - - # For an example response see https://github.com/csvalpha/amber-api/wiki/CardDAV-explained-with-examples - it_behaves_like '207 Multistatus' - it { expect(responses.length).to eq 5 } - - it do - expect(responses[0]['href']) - .to eq "/webdav/#{user.id}/#{user.webdav_secret_key}/contacts/books/#{group.id}/" - end - - it { expect(responses[0]['propstat']['prop']['displayname']).to eq group.name } - - it 'contains responses for the contacts' do - expect(responses[1..4].map { |r| r['href'] }) - .to match_array(group.users.map do |u| - "/webdav/#{user.id}/#{user.webdav_secret_key}/contacts/books/#{group.id}/#{u.id}" - end) - end - end - - context 'when requesting non member group' do - let(:request_url) do - "/webdav/#{user.id}/#{user.webdav_secret_key}/contacts/books/#{not_member_group.id}" - end - - subject(:request) do - current_session.request(request_url, method: 'PROPFIND', params: request_data) - end - - it_behaves_like '404 Not Found' - end - end - end -end diff --git a/spec/requests/v1/webdav/contact_spec.rb b/spec/requests/v1/webdav/contact_spec.rb deleted file mode 100644 index c054d8f5..00000000 --- a/spec/requests/v1/webdav/contact_spec.rb +++ /dev/null @@ -1,66 +0,0 @@ -require 'rails_helper' - -describe 'DAV4Rack::Carddav::Controller for DAV4Rack::Carddav::ContactResource' do - describe 'PROPFIND /webdav/:user_id/:key/contacts/books/:group_id/:contact_id', version: 1 do - let(:users) { create_list(:user, 4, :webdav_enabled, activated_at: Time.zone.now) } - let(:user) { users.first } - let(:group) do - create(:group, users:) - end - - before { group } - - context 'when requesting address data' do - let(:request_data) do - ' - - - - - ' - end - - context 'when with invalid secret' do - let(:request_url) do - "/webdav/#{user.id}/invalidsecret/contacts/books/#{group.id}/#{group.users[0].id}" - end - - subject(:request) do - current_session.request(request_url, method: 'PROPFIND', params: request_data) - end - - it_behaves_like '404 Not Found' - end - - context 'when with valid secret' do - let(:request_url) do - "/webdav/#{user.id}/#{user.webdav_secret_key}" \ - "/contacts/books/#{group.id}/#{group.users[0].id}" - end - let(:xml) { Hash.from_xml(request.body) } - let(:xml_response) { xml['multistatus']['response'] } - - subject(:request) do - current_session.request(request_url, method: 'PROPFIND', params: request_data) - end - - # For an example response see https://github.com/csvalpha/amber-api/wiki/CardDAV-explained-with-examples - it_behaves_like '207 Multistatus' - it do - expect(xml_response['href']).to eq( - "/webdav/#{user.id}/#{user.webdav_secret_key}" \ - "/contacts/books/#{group.id}/#{group.users[0].id}" - ) - end - - it { expect(xml_response['propstat']['prop']['displayname']).to eq group.users[0].id.to_s } - - it do - expect(xml_response['propstat']['prop']['address_data']) - .to eq(Webdav::Contact.user_to_vcard(group.users[0]).to_s) - end - end - end - end -end diff --git a/spec/requests/v1/webdav/principal_spec.rb b/spec/requests/v1/webdav/principal_spec.rb deleted file mode 100644 index 3d19fb38..00000000 --- a/spec/requests/v1/webdav/principal_spec.rb +++ /dev/null @@ -1,66 +0,0 @@ -require 'rails_helper' - -describe 'DAV4Rack::Carddav::Controller for DAV4Rack::Carddav::PrincipalResource' do - describe 'PROPFIND /webdav/:user_id/:key/contacts', version: 1 do - let(:user) do - create(:user, :webdav_enabled, activated_at: Time.zone.now) - end - - context 'when requesting resourcetype and current-user-principal' do - let(:request_data) do - ' - - - ' - end - - context 'when with valid secret' do - let(:request_url) { "/webdav/#{user.id}/#{user.webdav_secret_key}/contacts" } - let(:xml) { Hash.from_xml(request.body) } - let(:xml_response) { xml['multistatus']['response'] } - - subject(:request) do - current_session.request(request_url, method: 'PROPFIND', params: request_data) - end - - # For an example response see https://github.com/csvalpha/amber-api/wiki/CardDAV-explained-with-examples - it_behaves_like '207 Multistatus' - it do - expect(xml_response['propstat']['prop']['resourcetype'].keys) - .to contain_exactly('collection', 'principal') - end - - it do - expect(xml_response['propstat']['prop']['current_user_principal']['href']) - .to eq "/webdav/#{user.id}/#{user.webdav_secret_key}/contacts" - end - end - end - - context 'when requesting addressbook-home-set' do - let(:request_data) do - ' - - - ' - end - - context 'when with valid secret' do - let(:request_url) { "/webdav/#{user.id}/#{user.webdav_secret_key}/contacts/" } - let(:xml) { Hash.from_xml(request.body) } - let(:xml_response) { xml['multistatus']['response'] } - - subject(:request) do - current_session.request(request_url, method: 'PROPFIND', params: request_data) - end - - # For an example response see https://github.com/csvalpha/amber-api/wiki/CardDAV-explained-with-examples - it_behaves_like '207 Multistatus' - it do - expect(xml_response['propstat']['prop']['addressbook_home_set']['href']) - .to eq "/webdav/#{user.id}/#{user.webdav_secret_key}/contacts/books/" - end - end - end - end -end diff --git a/spec/resources/v1/user_resource_spec.rb b/spec/resources/v1/user_resource_spec.rb index 019c25a7..56280cd1 100644 --- a/spec/resources/v1/user_resource_spec.rb +++ b/spec/resources/v1/user_resource_spec.rb @@ -98,7 +98,7 @@ let(:another_user) { user } let(:fields) do basic_fields + update_fields + - read_fields + user_details_fields + %i[ical_secret_key webdav_secret_key] + read_fields + user_details_fields + %i[ical_secret_key] end it { expect(resource.fetchable_fields).to match_array(fields) } From a5bee82be7694074fb7a62bcbbb5a50d6ca829f6 Mon Sep 17 00:00:00 2001 From: Jorai Geertsema Date: Sat, 8 Feb 2025 00:14:55 +0100 Subject: [PATCH 2/5] updated gem.lock --- Gemfile.lock | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index fc36bcba..438decf6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,15 +1,3 @@ -GIT - remote: https://github.com/csvalpha/dav4rack.git - revision: 8541e53876d7a49a1c2d318e698f9dae88439e89 - ref: 8541e53 - specs: - dav4rack (0.2.11) - addressable (>= 2.8.0) - nokogiri (>= 1.12.5) - rack (>= 2.2.3) - uuidtools (>= 2.1.5) - webrick (>= 1.7.0) - GIT remote: https://github.com/heapsource/active_model_otp.git revision: 6ed9927ac2457b3fa7d59931f7758cac209c3b71 @@ -139,10 +127,6 @@ GEM crass (1.0.6) date (3.4.1) date (3.4.1-java) - dav4rack_ext (1.0.0) - dav4rack - http_router - vcard_parser (~> 0.0.8) debug_inspector (1.1.0) diff-lcs (1.5.0) docile (1.4.0) @@ -215,9 +199,6 @@ GEM http-cookie (1.0.4) domain_name (~> 0.5) http-form_data (2.3.0) - http_router (0.11.2) - rack (>= 1.0.0) - url_mount (~> 0.2.1) i18n (1.14.6) concurrent-ruby (~> 1.0) iban-tools (1.2.1) @@ -505,20 +486,15 @@ GEM unf_ext (0.0.8.1-x86-mingw32) unicode-display_width (2.1.0) uniform_notifier (1.16.0) - url_mount (0.2.1) - rack - uuidtools (2.2.0) validates_timeliness (7.0.0) activemodel (>= 7.0.0, < 8) timeliness (>= 0.3.10, < 1) - vcard_parser (0.0.9) vcr (6.1.0) vpim (24.2.20) webmock (3.14.0) addressable (>= 2.8.0) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) - webrick (1.7.0) websocket-driver (0.7.7) base64 websocket-extensions (>= 0.1.0) @@ -551,8 +527,6 @@ DEPENDENCIES colorize consistency_fail counter_culture (~> 3.8, >= 3.8.2) - dav4rack! - dav4rack_ext (~> 1.0) doorkeeper (~> 5.8, >= 5.8.1) doorkeeper-i18n (~> 5.2, >= 5.2.7) dotenv-rails From e53beb2ef9c6109dfcdf7d804f89d9993b1b5ac6 Mon Sep 17 00:00:00 2001 From: Jorai Geertsema Date: Sat, 8 Feb 2025 00:41:45 +0100 Subject: [PATCH 3/5] added migration --- config/routes.rb | 2 -- db/schema.rb | 6 +++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/config/routes.rb b/config/routes.rb index 7ecff655..3dc11a66 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,5 +1,3 @@ -require_relative 'routes/contact_sync_handler' - Rails.application.routes.draw do scope 'v1' do use_doorkeeper diff --git a/db/schema.rb b/db/schema.rb index e3514de9..57dc7635 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -9,7 +9,8 @@ # migrations use external dependencies or application code. # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2024_11_13_091607) do + +ActiveRecord::Schema[7.0].define(version: 2025_02_07_233328) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -473,7 +474,7 @@ t.index ["author_id"], name: "index_polls_on_author_id" t.index ["form_id"], name: "index_polls_on_form_id" end -3 + create_table "room_adverts", force: :cascade do |t| t.string "house_name", null: false t.string "contact", null: false @@ -558,7 +559,6 @@ t.string "digtus_subscription_preference", default: "physical" t.string "user_details_sharing_preference" t.boolean "allow_tomato_sharing" - t.string "webdav_secret_key" t.string "nickname" t.index ["deleted_at"], name: "index_users_on_deleted_at" t.index ["email"], name: "index_users_on_email", unique: true From 797c971983a65d1321db79406b90bc81f330ce41 Mon Sep 17 00:00:00 2001 From: Jorai Geertsema Date: Sat, 8 Feb 2025 01:32:23 +0100 Subject: [PATCH 4/5] forgot 1 line --- app/models/user.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/app/models/user.rb b/app/models/user.rb index 8c4fb9f5..07a4d39b 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -81,7 +81,6 @@ class User < ApplicationRecord # rubocop:disable Metrics/ClassLength after_commit :sync_mail_aliases scope :activated, (-> { where('activated_at < ?', Time.zone.now) }) - scope :contactsync_users, (-> { where.not(webdav_secret_key: nil) }) scope :tomato_users, (-> { where(allow_tomato_sharing: true) }) scope :login_enabled, (-> { where(login_enabled: true) }) scope :sidekiq_access, (-> { where(sidekiq_access: true) }) From 6deff6a76bc79d12b776e794f8d397d32d05ed50 Mon Sep 17 00:00:00 2001 From: Jorai Geertsema Date: Sat, 8 Feb 2025 01:33:09 +0100 Subject: [PATCH 5/5] forgot to add migration --- db/migrate/20250207233328_remove_contact_sync.rb | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 db/migrate/20250207233328_remove_contact_sync.rb diff --git a/db/migrate/20250207233328_remove_contact_sync.rb b/db/migrate/20250207233328_remove_contact_sync.rb new file mode 100644 index 00000000..8e5bae5c --- /dev/null +++ b/db/migrate/20250207233328_remove_contact_sync.rb @@ -0,0 +1,5 @@ +class RemoveContactSync < ActiveRecord::Migration[7.0] + def change + remove_column(:users, :webdav_secret_key, type: :string) + end +end