diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 657bb63edc2..c49c5e3747d 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -83,6 +83,7 @@ def create_free_user! UserMailer.welcome(@user).deliver_now notify_to_mentors(@user) notify_to_chat(@user) + Newspaper.publish(:student_or_trainee_create, @user) if @user.trainee? redirect_to root_url, notice: 'サインアップメールをお送りしました。メールからサインアップを完了させてください。' else render 'new' @@ -123,6 +124,7 @@ def create_user! UserMailer.welcome(@user).deliver_now notify_to_mentors(@user) notify_to_chat(@user) + Newspaper.publish(:student_or_trainee_create, @user) if @user.student? redirect_to root_url, notice: 'サインアップメールをお送りしました。メールからサインアップを完了させてください。' else render 'new' diff --git a/app/models/times_channel_creator.rb b/app/models/times_channel_creator.rb new file mode 100644 index 00000000000..25e293ada42 --- /dev/null +++ b/app/models/times_channel_creator.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +class TimesChannelCreator + def call(user) + raise ArgumentError, "#{user.login_name}は現役生または研修生ではありません。" unless user.student_or_trainee? + + times_channel = Discord::TimesChannel.new(user.login_name) + if times_channel.save + user.update(times_id: times_channel.id) + else + Rails.logger.warn "[Discord API] #{user.login_name}の分報チャンネルが作成できませんでした。" + end + end +end diff --git a/config/initializers/newspaper.rb b/config/initializers/newspaper.rb index e31740ace81..7450ea71ec0 100644 --- a/config/initializers/newspaper.rb +++ b/config/initializers/newspaper.rb @@ -26,6 +26,8 @@ Newspaper.subscribe(:correct_answer_save, CorrectAnswerNotifier.new) Newspaper.subscribe(:user_create, SignUpNotifier.new) + Newspaper.subscribe(:student_or_trainee_create, TimesChannelCreator.new) + Newspaper.subscribe(:regular_event_update, RegularEventUpdateNotifier.new) Newspaper.subscribe(:graduation_update, GraduationNotifier.new) diff --git a/db/migrate/20230208073717_add_times_id_to_users.rb b/db/migrate/20230208073717_add_times_id_to_users.rb new file mode 100644 index 00000000000..17b6430b0f5 --- /dev/null +++ b/db/migrate/20230208073717_add_times_id_to_users.rb @@ -0,0 +1,5 @@ +class AddTimesIdToUsers < ActiveRecord::Migration[6.1] + def change + add_column :users, :times_id, :string, comment: 'Snowflake ID' + end +end diff --git a/db/schema.rb b/db/schema.rb index 10a323059c6..02661c34854 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2022_12_24_091715) do +ActiveRecord::Schema.define(version: 2023_02_08_073717) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -655,6 +655,7 @@ t.string "profile_job" t.text "profile_text" t.string "feed_url" + t.string "times_id", comment: "Snowflake ID" t.index ["course_id"], name: "index_users_on_course_id" t.index ["email"], name: "index_users_on_email", unique: true t.index ["github_id"], name: "index_users_on_github_id", unique: true diff --git a/test/integration/discord/users_controller_test.rb b/test/integration/discord/users_controller_test.rb new file mode 100644 index 00000000000..7afcee23350 --- /dev/null +++ b/test/integration/discord/users_controller_test.rb @@ -0,0 +1,131 @@ +# frozen_string_literal: true + +require 'test_helper' + +module Discord + class UsersControllerTest < ActionDispatch::IntegrationTest + test 'POST create by student' do + Card.stub(:new, -> { FakeCard.new }) do + Subscription.stub(:new, -> { FakeSubscription.new }) do + Discord::TimesChannel.stub(:new, ->(_) { ValidTimesChannel.new }) do + assert_difference 'User.students.count', 1 do + post users_path, + params: { + user: { + adviser: 'false', + trainee: 'false', + company_id: '', + login_name: 'Piyopiyo-student', + email: 'piyopiyo-student@example.com', + name: '現役生です', + name_kana: 'ゲンエキセイデス', + description: '現役生と言います。よろしくお願いします。', + job: 'part_time_worker', + os: 'linux', + experience: 'inexperienced', + password: 'passW0rd1234', + password_confirmation: 'passW0rd1234', + coc: 1, + tos: 2 + } + } + end + end + end + end + assert_redirected_to root_url + + student = User.find_by(login_name: 'Piyopiyo-student') + assert_not_nil student.times_id + end + + test 'POST create by trainee' do + Discord::TimesChannel.stub(:new, ->(_) { ValidTimesChannel.new }) do + assert_difference 'User.trainees.count', 1 do + post users_path, + params: { + user: { + adviser: 'false', + trainee: 'true', + company_id: '123456789', + login_name: 'Piyopiyo-trainee', + email: 'piyopiyo-trainee@example.com', + name: '研修生です', + name_kana: 'ケンシュウセイデス', + description: '研修生と言います。よろしくお願いします。', + job: 'office_worker', + os: 'windows_wsl2', + experience: 'ruby', + password: 'passW0rd1234', + password_confirmation: 'passW0rd1234', + coc: 1, + tos: 2 + } + } + end + end + assert_redirected_to root_url + + trainee = User.find_by(login_name: 'Piyopiyo-trainee') + assert_not_nil trainee.times_id + end + + test 'POST create by adviser' do + Discord::TimesChannel.stub(:new, ->(_) { ValidTimesChannel.new }) do + assert_difference 'User.advisers.count', 1 do + post users_path, + params: { + user: { + adviser: 'true', + trainee: 'false', + company_id: '123456789', + login_name: 'Piyopiyo-adviser', + email: 'piyopiyo-adviser@example.com', + name: 'アドバイザーです', + name_kana: 'アドバイザーデス', + description: 'アドバイザーと言います。よろしくお願いします。', + password: 'passW0rd1234', + password_confirmation: 'passW0rd1234', + coc: 1, + tos: 2 + } + } + end + end + assert_redirected_to root_url + + adviser = User.find_by(login_name: 'Piyopiyo-adviser') + assert_nil adviser.times_id + end + + class FakeCard + def search(*) + nil + end + + def create(*) + { + id: 'fake_customer_0123456789' + }.stringify_keys + end + end + + class FakeSubscription + def create(*) + { + id: 'fake_subscription_0123456789' + }.stringify_keys + end + end + + class ValidTimesChannel + def save + true + end + + def id + 'fake_times_snowflake_0123456789' + end + end + end +end diff --git a/test/models/times_channel_creator_test.rb b/test/models/times_channel_creator_test.rb new file mode 100644 index 00000000000..593f0797d61 --- /dev/null +++ b/test/models/times_channel_creator_test.rb @@ -0,0 +1,64 @@ +# frozen_string_literal: true + +require 'test_helper' + +class TimesChannelCreatorTest < ActiveSupport::TestCase + test '#call' do + logs = [] + user = users(:hajime) + assert user.student? + + Rails.logger.stub(:warn, ->(message) { logs << message }) do + Discord::TimesChannel.stub(:new, ->(_) { InvalidTimesChannel.new }) do + TimesChannelCreator.new.call(user) + end + assert_nil user.times_id + assert_equal "[Discord API] #{user.login_name}の分報チャンネルが作成できませんでした。", logs.pop + + Discord::TimesChannel.stub(:new, ->(_) { ValidTimesChannel.new }) do + TimesChannelCreator.new.call(user) + end + assert_equal '1234567890123456789', user.times_id + assert_nil logs.last + end + end + + test '#call with role' do + user = users(:adminonly) + assert user.admin? + assert_raise ArgumentError do + TimesChannelCreator.new.call(user) + end + assert_not user.student_or_trainee? + + user = users(:mentormentaro) + assert user.mentor? + assert_raise ArgumentError do + TimesChannelCreator.new.call(user) + end + assert_not user.student_or_trainee? + + user = users(:senpai) + assert user.adviser? + assert_raise ArgumentError do + TimesChannelCreator.new.call(user) + end + assert_not user.student_or_trainee? + end + + class ValidTimesChannel + def save + true + end + + def id + '1234567890123456789' + end + end + + class InvalidTimesChannel + def save + false + end + end +end diff --git a/test/system/notification/signed_up_test.rb b/test/system/notification/signed_up_test.rb index f30f177a3b4..e0534494690 100644 --- a/test/system/notification/signed_up_test.rb +++ b/test/system/notification/signed_up_test.rb @@ -6,10 +6,14 @@ class Notification::SignedUpTest < ApplicationSystemTestCase setup do @delivery_mode = AbstractNotifier.delivery_mode AbstractNotifier.delivery_mode = :normal + + @bot_token = Discord::Server.authorize_token + Discord::Server.authorize_token = 'skip' end teardown do AbstractNotifier.delivery_mode = @delivery_mode + Discord::Server.authorize_token = @bot_token end test 'notify mentors when signed up as adviser' do diff --git a/test/system/sign_up_test.rb b/test/system/sign_up_test.rb index c131f05fba4..dcf428fec6e 100644 --- a/test/system/sign_up_test.rb +++ b/test/system/sign_up_test.rb @@ -3,6 +3,15 @@ require 'application_system_test_case' class SignUpTest < ApplicationSystemTestCase + setup do + @bot_token = Discord::Server.authorize_token + Discord::Server.authorize_token = 'skip' + end + + teardown do + Discord::Server.authorize_token = @bot_token + end + test 'sign up' do visit '/users/new' within 'form[name=user]' do