diff --git a/spec/requests/api/schemas/json/admin_user_list_response.json b/spec/requests/api/schemas/json/admin_user_list_response.json new file mode 100644 index 00000000000..926cb8a1f35 --- /dev/null +++ b/spec/requests/api/schemas/json/admin_user_list_response.json @@ -0,0 +1,122 @@ +{ + "type": "array", + "minItems": 1, + "uniqItems": true, + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "avatar_template": { + "type": "string" + }, + "email": { + "type": "string" + }, + "secondary_emails": { + "type": "array", + "items": [ + + ] + }, + "active": { + "type": "boolean" + }, + "admin": { + "type": "boolean" + }, + "moderator": { + "type": "boolean" + }, + "last_seen_at": { + "type": ["string", "null"] + }, + "last_emailed_at": { + "type": ["string", "null"] + }, + "created_at": { + "type": "string" + }, + "last_seen_age": { + "type": "" + }, + "last_emailed_age": { + "type": "" + }, + "created_at_age": { + "type": "" + }, + "trust_level": { + "type": "integer" + }, + "manual_locked_trust_level": { + "type": [ + "string", + "null" + ] + }, + "flag_level": { + "type": "integer" + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "time_read": { + "type": "integer" + }, + "staged": { + "type": "boolean" + }, + "days_visited": { + "type": "integer" + }, + "posts_read_count": { + "type": "integer" + }, + "topics_entered": { + "type": "integer" + }, + "post_count": { + "type": "integer" + } + }, + "required": [ + "id", + "username", + "name", + "avatar_template", + "active", + "admin", + "moderator", + "last_seen_at", + "last_emailed_at", + "created_at", + "last_seen_age", + "last_emailed_age", + "created_at_age", + "trust_level", + "manual_locked_trust_level", + "flag_level", + "title", + "time_read", + "staged", + "days_visited", + "posts_read_count", + "topics_entered", + "post_count" + ] + } +} diff --git a/spec/requests/api/schemas/json/admin_user_response.json b/spec/requests/api/schemas/json/admin_user_response.json new file mode 100644 index 00000000000..a48094a3eda --- /dev/null +++ b/spec/requests/api/schemas/json/admin_user_response.json @@ -0,0 +1,616 @@ +{ + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "avatar_template": { + "type": "string" + }, + "email": { + "type": "string" + }, + "secondary_emails": { + "type": "array", + "items": [ + + ] + }, + "active": { + "type": "boolean" + }, + "admin": { + "type": "boolean" + }, + "moderator": { + "type": "boolean" + }, + "last_seen_at": { + "type": ["string", "null"] + }, + "last_emailed_at": { + "type": ["string", "null"] + }, + "created_at": { + "type": "string" + }, + "last_seen_age": { + "type": "" + }, + "last_emailed_age": { + "type": "" + }, + "created_at_age": { + "type": "" + }, + "trust_level": { + "type": "integer" + }, + "manual_locked_trust_level": { + "type": [ + "string", + "null" + ] + }, + "flag_level": { + "type": "integer" + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "time_read": { + "type": "integer" + }, + "staged": { + "type": "boolean" + }, + "days_visited": { + "type": "integer" + }, + "posts_read_count": { + "type": "integer" + }, + "topics_entered": { + "type": "integer" + }, + "post_count": { + "type": "integer" + }, + "associated_accounts": { + "type": "array", + "items": [ + + ] + }, + "can_send_activation_email": { + "type": "boolean" + }, + "can_activate": { + "type": "boolean" + }, + "can_deactivate": { + "type": "boolean" + }, + "ip_address": { + "type": "string" + }, + "registration_ip_address": { + "type": [ + "string", + "null" + ] + }, + "can_grant_admin": { + "type": "boolean" + }, + "can_revoke_admin": { + "type": "boolean" + }, + "can_grant_moderation": { + "type": "boolean" + }, + "can_revoke_moderation": { + "type": "boolean" + }, + "can_impersonate": { + "type": "boolean" + }, + "like_count": { + "type": "integer" + }, + "like_given_count": { + "type": "integer" + }, + "topic_count": { + "type": "integer" + }, + "flags_given_count": { + "type": "integer" + }, + "flags_received_count": { + "type": "integer" + }, + "private_topics_count": { + "type": "integer" + }, + "can_delete_all_posts": { + "type": "boolean" + }, + "can_be_deleted": { + "type": "boolean" + }, + "can_be_anonymized": { + "type": "boolean" + }, + "can_be_merged": { + "type": "boolean" + }, + "full_suspend_reason": { + "type": [ + "string", + "null" + ] + }, + "silence_reason": { + "type": [ + "string", + "null" + ] + }, + "primary_group_id": { + "type": [ + "string", + "null" + ] + }, + "badge_count": { + "type": "integer" + }, + "warnings_received_count": { + "type": "integer" + }, + "bounce_score": { + "type": "" + }, + "reset_bounce_score_after": { + "type": [ + "string", + "null" + ] + }, + "can_view_action_logs": { + "type": "boolean" + }, + "can_disable_second_factor": { + "type": "boolean" + }, + "can_delete_sso_record": { + "type": "boolean" + }, + "api_key_count": { + "type": "integer" + }, + "single_sign_on_record": { + "type": [ + "string", + "null" + ] + }, + "approved_by": { + "type": ["object", "null"], + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "name": { + "type": "string" + }, + "avatar_template": { + "type": "string" + } + }, + "required": [ + "id", + "username", + "name", + "avatar_template" + ] + }, + "suspended_by": { + "type": [ + "string", + "null" + ] + }, + "silenced_by": { + "type": [ + "string", + "null" + ] + }, + "tl3_requirements": { + "type": "object", + "additionalProperties": false, + "properties": { + "time_period": { + "type": "integer" + }, + "requirements_met": { + "type": "boolean" + }, + "requirements_lost": { + "type": "boolean" + }, + "trust_level_locked": { + "type": "boolean" + }, + "on_grace_period": { + "type": "boolean" + }, + "days_visited": { + "type": "integer" + }, + "min_days_visited": { + "type": "integer" + }, + "num_topics_replied_to": { + "type": "integer" + }, + "min_topics_replied_to": { + "type": "integer" + }, + "topics_viewed": { + "type": "integer" + }, + "min_topics_viewed": { + "type": "integer" + }, + "posts_read": { + "type": "integer" + }, + "min_posts_read": { + "type": "integer" + }, + "topics_viewed_all_time": { + "type": "integer" + }, + "min_topics_viewed_all_time": { + "type": "integer" + }, + "posts_read_all_time": { + "type": "integer" + }, + "min_posts_read_all_time": { + "type": "integer" + }, + "num_flagged_posts": { + "type": "integer" + }, + "max_flagged_posts": { + "type": "integer" + }, + "num_flagged_by_users": { + "type": "integer" + }, + "max_flagged_by_users": { + "type": "integer" + }, + "num_likes_given": { + "type": "integer" + }, + "min_likes_given": { + "type": "integer" + }, + "num_likes_received": { + "type": "integer" + }, + "min_likes_received": { + "type": "integer" + }, + "num_likes_received_days": { + "type": "integer" + }, + "min_likes_received_days": { + "type": "integer" + }, + "num_likes_received_users": { + "type": "integer" + }, + "min_likes_received_users": { + "type": "integer" + }, + "penalty_counts": { + "type": "object", + "additionalProperties": false, + "properties": { + "silenced": { + "type": "integer" + }, + "suspended": { + "type": "integer" + }, + "total": { + "type": "integer" + } + }, + "required": [ + "silenced", + "suspended", + "total" + ] + } + }, + "required": [ + "time_period", + "requirements_met", + "requirements_lost", + "trust_level_locked", + "on_grace_period", + "days_visited", + "min_days_visited", + "num_topics_replied_to", + "min_topics_replied_to", + "topics_viewed", + "min_topics_viewed", + "posts_read", + "min_posts_read", + "topics_viewed_all_time", + "min_topics_viewed_all_time", + "posts_read_all_time", + "min_posts_read_all_time", + "num_flagged_posts", + "max_flagged_posts", + "num_flagged_by_users", + "max_flagged_by_users", + "num_likes_given", + "min_likes_given", + "num_likes_received", + "min_likes_received", + "num_likes_received_days", + "min_likes_received_days", + "num_likes_received_users", + "min_likes_received_users", + "penalty_counts" + ] + }, + "groups": { + "type": "array", + "items": [ + { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "automatic": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "display_name": { + "type": "string" + }, + "user_count": { + "type": "integer" + }, + "mentionable_level": { + "type": "integer" + }, + "messageable_level": { + "type": "integer" + }, + "visibility_level": { + "type": "integer" + }, + "primary_group": { + "type": "boolean" + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "grant_trust_level": { + "type": [ + "string", + "null" + ] + }, + "incoming_email": { + "type": [ + "string", + "null" + ] + }, + "has_messages": { + "type": "boolean" + }, + "flair_url": { + "type": [ + "string", + "null" + ] + }, + "flair_bg_color": { + "type": [ + "string", + "null" + ] + }, + "flair_color": { + "type": [ + "string", + "null" + ] + }, + "bio_raw": { + "type": [ + "string", + "null" + ] + }, + "bio_cooked": { + "type": [ + "string", + "null" + ] + }, + "bio_excerpt": { + "type": [ + "string", + "null" + ] + }, + "public_admission": { + "type": "boolean" + }, + "public_exit": { + "type": "boolean" + }, + "allow_membership_requests": { + "type": "boolean" + }, + "full_name": { + "type": [ + "string", + "null" + ] + }, + "default_notification_level": { + "type": "integer" + }, + "membership_request_template": { + "type": [ + "string", + "null" + ] + }, + "members_visibility_level": { + "type": "integer" + }, + "can_see_members": { + "type": "boolean" + }, + "can_admin_group": { + "type": "boolean" + }, + "publish_read_state": { + "type": "boolean" + } + }, + "required": [ + "id", + "automatic", + "name", + "display_name", + "user_count", + "mentionable_level", + "messageable_level", + "visibility_level", + "primary_group", + "title", + "grant_trust_level", + "incoming_email", + "has_messages", + "flair_url", + "flair_bg_color", + "flair_color", + "bio_raw", + "bio_cooked", + "bio_excerpt", + "public_admission", + "public_exit", + "allow_membership_requests", + "full_name", + "default_notification_level", + "membership_request_template", + "members_visibility_level", + "can_see_members", + "can_admin_group", + "publish_read_state" + ] + } + ] + } + }, + "required": [ + "id", + "username", + "name", + "avatar_template", + "active", + "admin", + "moderator", + "last_seen_at", + "last_emailed_at", + "created_at", + "last_seen_age", + "last_emailed_age", + "created_at_age", + "trust_level", + "manual_locked_trust_level", + "flag_level", + "title", + "time_read", + "staged", + "days_visited", + "posts_read_count", + "topics_entered", + "post_count", + "can_send_activation_email", + "can_activate", + "can_deactivate", + "ip_address", + "registration_ip_address", + "can_grant_admin", + "can_revoke_admin", + "can_grant_moderation", + "can_revoke_moderation", + "can_impersonate", + "like_count", + "like_given_count", + "topic_count", + "flags_given_count", + "flags_received_count", + "private_topics_count", + "can_delete_all_posts", + "can_be_deleted", + "can_be_anonymized", + "can_be_merged", + "full_suspend_reason", + "silence_reason", + "primary_group_id", + "badge_count", + "warnings_received_count", + "bounce_score", + "reset_bounce_score_after", + "can_view_action_logs", + "can_disable_second_factor", + "can_delete_sso_record", + "api_key_count", + "single_sign_on_record", + "approved_by", + "suspended_by", + "silenced_by", + "groups" + ] +} diff --git a/spec/requests/api/schemas/json/success_ok_response.json b/spec/requests/api/schemas/json/success_ok_response.json new file mode 100644 index 00000000000..3eff7837b80 --- /dev/null +++ b/spec/requests/api/schemas/json/success_ok_response.json @@ -0,0 +1,12 @@ +{ + "additionalProperties": false, + "properties": { + "success": { + "type": "string", + "example": "OK" + } + }, + "required": [ + "success" + ] +} diff --git a/spec/requests/api/schemas/json/user_actions_response.json b/spec/requests/api/schemas/json/user_actions_response.json new file mode 100644 index 00000000000..9c0204e129d --- /dev/null +++ b/spec/requests/api/schemas/json/user_actions_response.json @@ -0,0 +1,146 @@ +{ + "additionalProperties": false, + "properties": { + "user_actions": { + "type": "array", + "items": [ + { + "type": "object", + "additionalProperties": false, + "properties": { + "excerpt": { + "type": "string" + }, + "action_type": { + "type": "integer" + }, + "created_at": { + "type": "string" + }, + "avatar_template": { + "type": "string" + }, + "acting_avatar_template": { + "type": "string" + }, + "slug": { + "type": "string" + }, + "topic_id": { + "type": "integer" + }, + "target_user_id": { + "type": "integer" + }, + "target_name": { + "type": [ + "string", + "null" + ] + }, + "target_username": { + "type": "string" + }, + "post_number": { + "type": "integer" + }, + "post_id": { + "type": [ + "string", + "null" + ] + }, + "username": { + "type": "string" + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "user_id": { + "type": "integer" + }, + "acting_username": { + "type": "string" + }, + "acting_name": { + "type": [ + "string", + "null" + ] + }, + "acting_user_id": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "deleted": { + "type": "boolean" + }, + "hidden": { + "type": [ + "string", + "null" + ] + }, + "post_type": { + "type": [ + "string", + "null" + ] + }, + "action_code": { + "type": [ + "string", + "null" + ] + }, + "category_id": { + "type": "integer" + }, + "closed": { + "type": "boolean" + }, + "archived": { + "type": "boolean" + } + }, + "required": [ + "excerpt", + "action_type", + "created_at", + "avatar_template", + "acting_avatar_template", + "slug", + "topic_id", + "target_user_id", + "target_name", + "target_username", + "post_number", + "post_id", + "username", + "name", + "user_id", + "acting_username", + "acting_name", + "acting_user_id", + "title", + "deleted", + "hidden", + "post_type", + "action_code", + "category_id", + "closed", + "archived" + ] + } + ] + } + }, + "required": [ + "user_actions" + ] +} diff --git a/spec/requests/api/schemas/json/user_delete_request.json b/spec/requests/api/schemas/json/user_delete_request.json new file mode 100644 index 00000000000..c7c7b83a266 --- /dev/null +++ b/spec/requests/api/schemas/json/user_delete_request.json @@ -0,0 +1,17 @@ +{ + "additionalProperties": false, + "properties": { + "delete_posts": { + "type": "boolean" + }, + "block_email": { + "type": "boolean" + }, + "block_urls": { + "type": "boolean" + }, + "block_ip": { + "type": "boolean" + } + } +} diff --git a/spec/requests/api/schemas/json/user_delete_response.json b/spec/requests/api/schemas/json/user_delete_response.json new file mode 100644 index 00000000000..1265c7ff32b --- /dev/null +++ b/spec/requests/api/schemas/json/user_delete_response.json @@ -0,0 +1,11 @@ +{ + "additionalProperties": false, + "properties": { + "deleted": { + "type": "boolean" + } + }, + "required": [ + "deleted" + ] +} diff --git a/spec/requests/api/schemas/json/user_refresh_gravatar_response.json b/spec/requests/api/schemas/json/user_refresh_gravatar_response.json new file mode 100644 index 00000000000..1bbfdc02ee6 --- /dev/null +++ b/spec/requests/api/schemas/json/user_refresh_gravatar_response.json @@ -0,0 +1,15 @@ +{ + "additionalProperties": false, + "properties": { + "gravatar_upload_id": { + "type": ["integer", "null"] + }, + "gravatar_avatar_template": { + "type": ["string", "null"] + } + }, + "required": [ + "gravatar_upload_id", + "gravatar_avatar_template" + ] +} diff --git a/spec/requests/api/schemas/json/user_update_avatar_request.json b/spec/requests/api/schemas/json/user_update_avatar_request.json new file mode 100644 index 00000000000..db3b8919bf0 --- /dev/null +++ b/spec/requests/api/schemas/json/user_update_avatar_request.json @@ -0,0 +1,21 @@ +{ + "additionalProperties": false, + "properties": { + "upload_id": { + "type": "integer" + }, + "type": { + "type": "string", + "enum": [ + "uploaded", + "custom", + "gravatar", + "system" + ] + } + }, + "required": [ + "upload_id", + "type" + ] +} diff --git a/spec/requests/api/schemas/json/user_update_email_request.json b/spec/requests/api/schemas/json/user_update_email_request.json new file mode 100644 index 00000000000..3dc2a778f45 --- /dev/null +++ b/spec/requests/api/schemas/json/user_update_email_request.json @@ -0,0 +1,12 @@ +{ + "additionalProperties": false, + "properties": { + "email": { + "type": "string", + "format": "email" + } + }, + "required": [ + "email" + ] +} diff --git a/spec/requests/api/schemas/json/users_public_list_response.json b/spec/requests/api/schemas/json/users_public_list_response.json new file mode 100644 index 00000000000..a99098b313d --- /dev/null +++ b/spec/requests/api/schemas/json/users_public_list_response.json @@ -0,0 +1,109 @@ +{ + "additionalProperties": false, + "properties": { + "directory_items": { + "type": "array", + "items": [ + { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "likes_received": { + "type": "integer" + }, + "likes_given": { + "type": "integer" + }, + "topics_entered": { + "type": "integer" + }, + "topic_count": { + "type": "integer" + }, + "post_count": { + "type": "integer" + }, + "posts_read": { + "type": "integer" + }, + "days_visited": { + "type": "integer" + }, + "user": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "avatar_template": { + "type": "string" + }, + "title": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "id", + "username", + "name", + "avatar_template", + "title" + ] + } + }, + "required": [ + "id", + "likes_received", + "likes_given", + "topics_entered", + "topic_count", + "post_count", + "posts_read", + "days_visited", + "user" + ] + } + ] + }, + "meta": { + "type": "object", + "additionalProperties": false, + "properties": { + "last_updated_at": { + "type": ["string", "null"] + }, + "total_rows_directory_items": { + "type": "integer" + }, + "load_more_directory_items": { + "type": "string" + } + }, + "required": [ + "last_updated_at", + "total_rows_directory_items", + "load_more_directory_items" + ] + } + }, + "required": [ + "directory_items", + "meta" + ] +} diff --git a/spec/requests/api/shared/shared_examples.rb b/spec/requests/api/shared/shared_examples.rb index f6e732dce54..eb21df58c5d 100644 --- a/spec/requests/api/shared/shared_examples.rb +++ b/spec/requests/api/shared/shared_examples.rb @@ -10,7 +10,13 @@ RSpec.shared_examples "a JSON endpoint" do |expected_response_status| unless valid # for debugging puts puts "RESPONSE: #{params}" - puts "VALIDATION DETAILS: #{schemer.validate(params).to_a[0]["details"]}" + validation_result = schemer.validate(params).to_a[0] + details = validation_result["details"] + if details + puts "VALIDATION DETAILS: #{details}" + else + puts "POSSIBLE ISSUE W/: #{validation_result['data_pointer']}" + end end expect(valid).to eq(true) end @@ -23,19 +29,21 @@ RSpec.shared_examples "a JSON endpoint" do |expected_response_status| describe "request body" do it "matches the documented request schema" do |example| - schemer = JSONSchemer.schema(expected_request_schema) - expect_schema_valid(schemer, params) + if expected_request_schema + schemer = JSONSchemer.schema(expected_request_schema) + expect_schema_valid(schemer, params) + end end end describe "response body" do let(:json_response) { JSON.parse(response.body) } - it "matches the documented response schema" do |example| - schemer = JSONSchemer.schema( - expected_response_schema, - ) - expect_schema_valid(schemer, json_response) + it "matches the documented response schema" do |example| + if expected_response_schema + schemer = JSONSchemer.schema(expected_response_schema) + expect_schema_valid(schemer, json_response) + end end end end diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index efc14081b69..23179e4f195 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -5,6 +5,13 @@ describe 'users' do let(:'Api-Key') { Fabricate(:api_key).key } let(:'Api-Username') { 'system' } + let(:admin) { Fabricate(:admin) } + + before do + SiteSetting.tagging_enabled = true + Jobs.run_immediately! + sign_in(admin) + end path '/users.json' do @@ -99,4 +106,358 @@ describe 'users' do end end + path '/u/by-external/{provider}/{external_id}.json' do + + get 'Get a user by identity provider external ID' do + tags 'Users' + consumes 'application/json' + parameter name: 'Api-Key', in: :header, type: :string, required: true + parameter name: 'Api-Username', in: :header, type: :string, required: true + parameter name: :provider, + in: :path, + type: :string, + required: true, + description: "Authentication provider name. Can be found in the provider callback URL: `/auth/{provider}/callback`" + parameter name: :external_id, in: :path, type: :string, required: true + + produces 'application/json' + response '200', 'user response' do + schema '$ref' => '#/components/schemas/user_response' + + let(:user) { Fabricate(:user) } + let(:provider) { 'google_oauth2' } + let(:external_id) { 'myuid' } + + before do + SiteSetting.enable_google_oauth2_logins = true + UserAssociatedAccount.create!(user: user, provider_uid: 'myuid', provider_name: 'google_oauth2') + end + + run_test! + end + end + end + + path '/u/{username}/preferences/avatar/pick.json' do + + put 'Update avatar' do + tags 'Users' + consumes 'application/json' + expected_request_schema = load_spec_schema('user_update_avatar_request') + + parameter name: :username, in: :path, type: :string, required: true + parameter name: :params, in: :body, schema: expected_request_schema + + produces 'application/json' + response '200', 'avatar updated' do + expected_response_schema = load_spec_schema('success_ok_response') + + let(:user) { Fabricate(:user) } + let(:username) { user.username } + let(:upload) { Fabricate(:upload, user: user) } + let(:params) { { 'upload_id' => upload.id, 'type' => 'uploaded' } } + + schema(expected_response_schema) + + it_behaves_like "a JSON endpoint", 200 do + let(:expected_response_schema) { expected_response_schema } + let(:expected_request_schema) { expected_request_schema } + end + end + end + + end + + path '/u/{username}/preferences/email.json' do + + put 'Update email' do + tags 'Users' + consumes 'application/json' + expected_request_schema = load_spec_schema('user_update_email_request') + + parameter name: :username, in: :path, type: :string, required: true + parameter name: :params, in: :body, schema: expected_request_schema + + produces 'application/json' + response '200', 'email updated' do + + let(:user) { Fabricate(:user) } + let(:username) { user.username } + let(:params) { { 'email' => "test@example.com" } } + + expected_response_schema = nil + + it_behaves_like "a JSON endpoint", 200 do + let(:expected_response_schema) { expected_response_schema } + let(:expected_request_schema) { expected_request_schema } + end + end + end + + end + + path '/directory_items.json' do + + get 'Get a public list of users' do + tags 'Users' + consumes 'application/json' + expected_request_schema = nil + + parameter name: :period, + in: :query, + schema: { + type: :string, + enum: ['daily', 'weekly', 'monthly', 'quarterly', 'yearly', 'all'] + }, + required: true + parameter name: :order, + in: :query, + schema: { + type: :string, + enum: [ + 'likes_received', + 'likes_given', + 'topic_count', + 'post_count', + 'topics_entered', + 'posts_read', + 'days_visited' + ] + }, + required: true + parameter name: :asc, + in: :query, + schema: { + type: :string, + enum: ['true'] + } + parameter name: :page, in: :query, type: :integer + + produces 'application/json' + response '200', 'directory items response' do + + let(:period) { 'weekly' } + let(:order) { 'likes_received' } + let(:asc) { 'true' } + let(:page) { 0 } + + expected_response_schema = load_spec_schema('users_public_list_response') + schema(expected_response_schema) + + it_behaves_like "a JSON endpoint", 200 do + let(:expected_response_schema) { expected_response_schema } + let(:expected_request_schema) { expected_request_schema } + end + end + end + + end + + path '/admin/users/{id}.json' do + + get 'Get a user by id' do + tags 'Users', 'Admin' + consumes 'application/json' + expected_request_schema = nil + + parameter name: :id, in: :path, type: :integer, required: true + + produces 'application/json' + response '200', 'response' do + + let(:id) { Fabricate(:user).id } + + expected_response_schema = load_spec_schema('admin_user_response') + schema(expected_response_schema) + + it_behaves_like "a JSON endpoint", 200 do + let(:expected_response_schema) { expected_response_schema } + let(:expected_request_schema) { expected_request_schema } + end + end + end + + delete 'Delete a user' do + tags 'Users', 'Admin' + consumes 'application/json' + expected_request_schema = load_spec_schema('user_delete_request') + + parameter name: :id, in: :path, type: :integer, required: true + parameter name: :params, in: :body, schema: expected_request_schema + + produces 'application/json' + response '200', 'response' do + + let(:id) { Fabricate(:user).id } + let(:params) { { + 'delete_posts' => true, + 'block_email' => false, + 'block_urls' => false, + 'block_ip' => false + } } + + expected_response_schema = load_spec_schema('user_delete_response') + schema(expected_response_schema) + + it_behaves_like "a JSON endpoint", 200 do + let(:expected_response_schema) { expected_response_schema } + let(:expected_request_schema) { expected_request_schema } + end + end + end + + end + + path '/admin/users/{id}/log_out.json' do + + post 'Log a user out' do + tags 'Users', 'Admin' + consumes 'application/json' + expected_request_schema = nil + + parameter name: :id, in: :path, type: :integer, required: true + + produces 'application/json' + response '200', 'response' do + + let(:id) { Fabricate(:user).id } + + expected_response_schema = load_spec_schema('success_ok_response') + schema(expected_response_schema) + + it_behaves_like "a JSON endpoint", 200 do + let(:expected_response_schema) { expected_response_schema } + let(:expected_request_schema) { expected_request_schema } + end + end + end + end + + path '/user_avatar/{username}/refresh_gravatar.json' do + + before do + stub_request(:get, /https:\/\/www.gravatar.com\/avatar\/\w+.png\?d=404&reset_cache=\S+&s=360/). + with( + headers: { + 'Accept' => '*/*', + 'Accept-Encoding' => 'gzip', + 'Host' => 'www.gravatar.com' + }). + to_return(status: 200, body: "", headers: {}) + end + + post 'Refresh gravatar' do + tags 'Users', 'Admin' + consumes 'application/json' + expected_request_schema = nil + + parameter name: :username, in: :path, type: :string, required: true + + produces 'application/json' + response '200', 'response' do + + let(:user) { Fabricate(:user) } + let(:username) { user.username } + + expected_response_schema = load_spec_schema('user_refresh_gravatar_response') + schema(expected_response_schema) + + it_behaves_like "a JSON endpoint", 200 do + let(:expected_response_schema) { expected_response_schema } + let(:expected_request_schema) { expected_request_schema } + end + end + end + end + + path '/admin/users/list/{flag}.json' do + + get 'Get a list of users' do + tags 'Users', 'Admin' + consumes 'application/json' + expected_request_schema = nil + + parameter name: :flag, + in: :path, + schema: { + type: :string, + enum: ['active', 'new', 'staff', 'suspended', 'blocked', 'suspect'] + }, + required: true + parameter name: :order, + in: :query, + schema: { + type: :string, + enum: [ + 'created', + 'last_emailed', + 'seen', + 'username', + 'email', + 'trust_level', + 'days_visited', + 'posts_read', + 'topics_viewed', + 'posts', + 'read_time' + ] + } + parameter name: :asc, + in: :query, + schema: { + type: :string, + enum: ['true'] + } + parameter name: :page, in: :query, type: :integer + parameter name: :show_emails, in: :query, type: :boolean + + produces 'application/json' + response '200', 'response' do + + let(:flag) { 'active' } + let(:order) { 'created' } + let(:asc) { 'true' } + let(:page) { 0 } + let(:show_emails) { false } + + expected_response_schema = load_spec_schema('admin_user_list_response') + schema(expected_response_schema) + + it_behaves_like "a JSON endpoint", 200 do + let(:expected_response_schema) { expected_response_schema } + let(:expected_request_schema) { expected_request_schema } + end + end + end + end + + path '/user_actions.json' do + + get 'Get a list of user actions' do + tags 'Users' + consumes 'application/json' + expected_request_schema = nil + + parameter name: :offset, in: :query, type: :integer, required: true + parameter name: :username, in: :query, type: :string, required: true + parameter name: :filter, in: :query, type: :string, required: true + + produces 'application/json' + response '200', 'response' do + + let(:offset) { 0 } + let(:username) { Fabricate(:user).username } + let(:filter) { '4,5' } + + expected_response_schema = load_spec_schema('user_actions_response') + schema(expected_response_schema) + + it_behaves_like "a JSON endpoint", 200 do + let(:expected_response_schema) { expected_response_schema } + let(:expected_request_schema) { expected_request_schema } + end + end + end + end + end