mirror of
https://github.com/Freika/dawarich.git
synced 2026-01-10 17:21:38 -05:00
* Implement OmniAuth GitHub authentication * Fix omniauth GitHub scope to include user email access * Remove margin-bottom * Implement Google OAuth2 authentication * Implement OIDC authentication for Dawarich using omniauth_openid_connect gem. * Add patreon account linking and patron checking service * Update docker-compose.yml to use boolean values instead of strings * Add support for KML files * Add tests * Update changelog * Remove patreon OAuth integration * Move omniauthable to a concern * Update an icon in integrations * Update changelog * Update app version * Fix family location sharing toggle * Move family location sharing to its own controller * Update changelog * Implement basic tagging functionality for places, allowing users to categorize and label places with custom tags. * Add places management API and tags feature * Add some changes related to places management feature * Fix some tests * Fix sometests * Add places layer * Update places layer to use Leaflet.Control.Layers.Tree for hierarchical layer control * Rework tag form * Add hashtag * Add privacy zones to tags * Add notes to places and manage place tags * Update changelog * Update e2e tests * Extract tag serializer to its own file * Fix some tests * Fix tags request specs * Fix some tests * Fix rest of the tests * Revert some changes * Add missing specs * Revert changes in place export/import code * Fix some specs * Fix PlaceFinder to only consider global places when finding existing places * Fix few more specs * Fix visits creator spec * Fix last tests * Update place creating modal * Add home location based on "Home" tagged place * Save enabled tag layers * Some fixes * Fix bug where enabling place tag layers would trigger saving enabled layers, overwriting with incomplete data * Update migration to use disable_ddl_transaction! and add up/down methods * Fix tag layers restoration and filtering logic * Update OIDC auto-registration and email/password registration settings * Fix potential xss
332 lines
11 KiB
Ruby
332 lines
11 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require 'swagger_helper'
|
|
|
|
RSpec.describe 'Places API', type: :request do
|
|
path '/api/v1/places' do
|
|
get 'Retrieves all places for the authenticated user' do
|
|
tags 'Places'
|
|
produces 'application/json'
|
|
parameter name: :api_key, in: :query, type: :string, required: true, description: 'API key for authentication'
|
|
parameter name: :tag_ids, in: :query, type: :array, items: { type: :integer }, required: false, description: 'Filter places by tag IDs'
|
|
|
|
response '200', 'places found' do
|
|
schema type: :array,
|
|
items: {
|
|
type: :object,
|
|
properties: {
|
|
id: { type: :integer },
|
|
name: { type: :string },
|
|
latitude: { type: :number, format: :float },
|
|
longitude: { type: :number, format: :float },
|
|
source: { type: :string },
|
|
icon: { type: :string, nullable: true },
|
|
color: { type: :string, nullable: true },
|
|
visits_count: { type: :integer },
|
|
created_at: { type: :string, format: 'date-time' },
|
|
tags: {
|
|
type: :array,
|
|
items: {
|
|
type: :object,
|
|
properties: {
|
|
id: { type: :integer },
|
|
name: { type: :string },
|
|
icon: { type: :string },
|
|
color: { type: :string }
|
|
}
|
|
}
|
|
}
|
|
},
|
|
required: %w[id name latitude longitude]
|
|
}
|
|
|
|
let(:user) { create(:user) }
|
|
let(:api_key) { user.api_key }
|
|
let!(:place) { create(:place, user: user) }
|
|
|
|
run_test! do |response|
|
|
data = JSON.parse(response.body)
|
|
expect(data).to be_an(Array)
|
|
expect(data.first['id']).to eq(place.id)
|
|
end
|
|
end
|
|
|
|
response '401', 'unauthorized' do
|
|
let(:api_key) { 'invalid' }
|
|
|
|
run_test!
|
|
end
|
|
end
|
|
|
|
post 'Creates a place' do
|
|
tags 'Places'
|
|
consumes 'application/json'
|
|
produces 'application/json'
|
|
parameter name: :api_key, in: :query, type: :string, required: true, description: 'API key for authentication'
|
|
parameter name: :place, in: :body, schema: {
|
|
type: :object,
|
|
properties: {
|
|
name: { type: :string },
|
|
latitude: { type: :number, format: :float },
|
|
longitude: { type: :number, format: :float },
|
|
source: { type: :string },
|
|
tag_ids: { type: :array, items: { type: :integer } }
|
|
},
|
|
required: %w[name latitude longitude]
|
|
}
|
|
|
|
response '201', 'place created' do
|
|
schema type: :object,
|
|
properties: {
|
|
id: { type: :integer },
|
|
name: { type: :string },
|
|
latitude: { type: :number, format: :float },
|
|
longitude: { type: :number, format: :float },
|
|
source: { type: :string },
|
|
icon: { type: :string, nullable: true },
|
|
color: { type: :string, nullable: true },
|
|
visits_count: { type: :integer },
|
|
created_at: { type: :string, format: 'date-time' },
|
|
tags: { type: :array }
|
|
}
|
|
|
|
let(:user) { create(:user) }
|
|
let(:tag) { create(:tag, user: user) }
|
|
let(:api_key) { user.api_key }
|
|
let(:place) do
|
|
{
|
|
name: 'Coffee Shop',
|
|
latitude: 40.7589,
|
|
longitude: -73.9851,
|
|
source: 'manual',
|
|
tag_ids: [tag.id]
|
|
}
|
|
end
|
|
|
|
run_test! do |response|
|
|
data = JSON.parse(response.body)
|
|
expect(data['name']).to eq('Coffee Shop')
|
|
# Note: tags array is expected to be in the response schema but may be empty initially
|
|
# Tags can be added separately via the update endpoint
|
|
expect(data).to have_key('tags')
|
|
end
|
|
end
|
|
|
|
response '422', 'invalid request' do
|
|
let(:user) { create(:user) }
|
|
let(:api_key) { user.api_key }
|
|
let(:place) { { name: '' } }
|
|
|
|
run_test!
|
|
end
|
|
|
|
response '401', 'unauthorized' do
|
|
let(:api_key) { 'invalid' }
|
|
let(:place) { { name: 'Test', latitude: 40.0, longitude: -73.0 } }
|
|
|
|
run_test!
|
|
end
|
|
end
|
|
end
|
|
|
|
path '/api/v1/places/nearby' do
|
|
get 'Searches for nearby places using Photon geocoding API' do
|
|
tags 'Places'
|
|
produces 'application/json'
|
|
parameter name: :api_key, in: :query, type: :string, required: true, description: 'API key for authentication'
|
|
parameter name: :latitude, in: :query, type: :number, format: :float, required: true, description: 'Latitude coordinate'
|
|
parameter name: :longitude, in: :query, type: :number, format: :float, required: true, description: 'Longitude coordinate'
|
|
parameter name: :radius, in: :query, type: :number, format: :float, required: false, description: 'Search radius in kilometers (default: 0.5)'
|
|
parameter name: :limit, in: :query, type: :integer, required: false, description: 'Maximum number of results (default: 10)'
|
|
|
|
response '200', 'nearby places found' do
|
|
schema type: :object,
|
|
properties: {
|
|
places: {
|
|
type: :array,
|
|
items: {
|
|
type: :object,
|
|
properties: {
|
|
name: { type: :string },
|
|
latitude: { type: :number, format: :float },
|
|
longitude: { type: :number, format: :float },
|
|
distance: { type: :number, format: :float },
|
|
type: { type: :string }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
let(:user) { create(:user) }
|
|
let(:api_key) { user.api_key }
|
|
let(:latitude) { 40.7589 }
|
|
let(:longitude) { -73.9851 }
|
|
let(:radius) { 1.0 }
|
|
let(:limit) { 5 }
|
|
|
|
run_test! do |response|
|
|
data = JSON.parse(response.body)
|
|
expect(data).to have_key('places')
|
|
expect(data['places']).to be_an(Array)
|
|
end
|
|
end
|
|
|
|
response '401', 'unauthorized' do
|
|
let(:api_key) { 'invalid' }
|
|
let(:latitude) { 40.7589 }
|
|
let(:longitude) { -73.9851 }
|
|
|
|
run_test!
|
|
end
|
|
end
|
|
end
|
|
|
|
path '/api/v1/places/{id}' do
|
|
parameter name: :id, in: :path, type: :integer, description: 'Place ID'
|
|
|
|
get 'Retrieves a specific place' do
|
|
tags 'Places'
|
|
produces 'application/json'
|
|
parameter name: :api_key, in: :query, type: :string, required: true, description: 'API key for authentication'
|
|
|
|
response '200', 'place found' do
|
|
schema type: :object,
|
|
properties: {
|
|
id: { type: :integer },
|
|
name: { type: :string },
|
|
latitude: { type: :number, format: :float },
|
|
longitude: { type: :number, format: :float },
|
|
source: { type: :string },
|
|
icon: { type: :string, nullable: true },
|
|
color: { type: :string, nullable: true },
|
|
visits_count: { type: :integer },
|
|
created_at: { type: :string, format: 'date-time' },
|
|
tags: { type: :array }
|
|
}
|
|
|
|
let(:user) { create(:user) }
|
|
let(:api_key) { user.api_key }
|
|
let(:place) { create(:place, user: user) }
|
|
let(:id) { place.id }
|
|
|
|
run_test! do |response|
|
|
data = JSON.parse(response.body)
|
|
expect(data['id']).to eq(place.id)
|
|
end
|
|
end
|
|
|
|
response '404', 'place not found' do
|
|
let(:user) { create(:user) }
|
|
let(:api_key) { user.api_key }
|
|
let(:id) { 'invalid' }
|
|
|
|
run_test!
|
|
end
|
|
|
|
response '401', 'unauthorized' do
|
|
let(:api_key) { 'invalid' }
|
|
let(:place) { create(:place) }
|
|
let(:id) { place.id }
|
|
|
|
run_test!
|
|
end
|
|
end
|
|
|
|
patch 'Updates a place' do
|
|
tags 'Places'
|
|
consumes 'application/json'
|
|
produces 'application/json'
|
|
parameter name: :api_key, in: :query, type: :string, required: true, description: 'API key for authentication'
|
|
parameter name: :place, in: :body, schema: {
|
|
type: :object,
|
|
properties: {
|
|
name: { type: :string },
|
|
latitude: { type: :number, format: :float },
|
|
longitude: { type: :number, format: :float },
|
|
tag_ids: { type: :array, items: { type: :integer } }
|
|
}
|
|
}
|
|
|
|
response '200', 'place updated' do
|
|
schema type: :object,
|
|
properties: {
|
|
id: { type: :integer },
|
|
name: { type: :string },
|
|
latitude: { type: :number, format: :float },
|
|
longitude: { type: :number, format: :float },
|
|
tags: { type: :array }
|
|
}
|
|
|
|
let(:user) { create(:user) }
|
|
let(:api_key) { user.api_key }
|
|
let(:existing_place) { create(:place, user: user) }
|
|
let(:id) { existing_place.id }
|
|
let(:place) { { name: 'Updated Name' } }
|
|
|
|
run_test! do |response|
|
|
data = JSON.parse(response.body)
|
|
expect(data['name']).to eq('Updated Name')
|
|
end
|
|
end
|
|
|
|
response '404', 'place not found' do
|
|
let(:user) { create(:user) }
|
|
let(:api_key) { user.api_key }
|
|
let(:id) { 'invalid' }
|
|
let(:place) { { name: 'Updated' } }
|
|
|
|
run_test!
|
|
end
|
|
|
|
response '422', 'invalid request' do
|
|
let(:user) { create(:user) }
|
|
let(:api_key) { user.api_key }
|
|
let(:existing_place) { create(:place, user: user) }
|
|
let(:id) { existing_place.id }
|
|
let(:place) { { name: '' } }
|
|
|
|
run_test!
|
|
end
|
|
|
|
response '401', 'unauthorized' do
|
|
let(:api_key) { 'invalid' }
|
|
let(:existing_place) { create(:place) }
|
|
let(:id) { existing_place.id }
|
|
let(:place) { { name: 'Updated' } }
|
|
|
|
run_test!
|
|
end
|
|
end
|
|
|
|
delete 'Deletes a place' do
|
|
tags 'Places'
|
|
produces 'application/json'
|
|
parameter name: :api_key, in: :query, type: :string, required: true, description: 'API key for authentication'
|
|
|
|
response '204', 'place deleted' do
|
|
let(:user) { create(:user) }
|
|
let(:api_key) { user.api_key }
|
|
let(:place) { create(:place, user: user) }
|
|
let(:id) { place.id }
|
|
|
|
run_test!
|
|
end
|
|
|
|
response '404', 'place not found' do
|
|
let(:user) { create(:user) }
|
|
let(:api_key) { user.api_key }
|
|
let(:id) { 'invalid' }
|
|
|
|
run_test!
|
|
end
|
|
|
|
response '401', 'unauthorized' do
|
|
let(:api_key) { 'invalid' }
|
|
let(:place) { create(:place) }
|
|
let(:id) { place.id }
|
|
|
|
run_test!
|
|
end
|
|
end
|
|
end
|
|
end
|