diff --git a/.env.production.sample b/.env.production.sample index ebb0788781d59a..5fb6acb965b1a1 100644 --- a/.env.production.sample +++ b/.env.production.sample @@ -229,3 +229,13 @@ STREAMING_CLUSTER_NUM=1 # http_proxy=http://gateway.local:8118 # Access control for hidden service. # ALLOW_ACCESS_TO_HIDDEN_SERVICE=true + +# Facebook +FACEBOOK_APP_ID=xxxxxxxx +FACEBOOK_APP_SECRET=xxxxxxxx +FACEBOOK_CALLBACK_URL=http://example.com/auth/auth/facebook/callback +FACEBOOK_PIXEL_ID=xxxxxxxx + +#GitHub +GITHUB_KEY=xxxxxxx +GITHUB_SECRET=xxxxxxxxxxxxxx diff --git a/Gemfile b/Gemfile index 7a6e1568d28c35..6a3187dccbc940 100644 --- a/Gemfile +++ b/Gemfile @@ -92,6 +92,16 @@ gem 'webpush' gem 'json-ld', '~> 2.2' gem 'rdf-normalize', '~> 0.3' +# Added by Kibousoft +gem 'ruby-bbcode' +gem 'omniauth-github', '~> 1.3.0' +gem 'omniauth-facebook', '~> 4.0.0' +gem 'react-rails-img' +gem 'json' +gem 'twitter-bootstrap-rails' +gem 'therubyracer' +gem 'jquery-rails' + group :development, :test do gem 'fabrication', '~> 2.20' gem 'fuubar', '~> 2.2' diff --git a/Gemfile.lock b/Gemfile.lock index e1929a05c83069..81fa27b08bd1dd 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -88,6 +88,10 @@ GEM aws-sdk-kms (~> 1) aws-sigv4 (~> 1.0) aws-sigv4 (1.0.2) + babel-source (5.8.35) + babel-transpiler (0.7.0) + babel-source (>= 4.0, < 6) + execjs (~> 2.0) bcrypt (3.1.12) benchmark-ips (2.7.2) better_errors (2.4.0) @@ -146,6 +150,7 @@ GEM climate_control (>= 0.0.3, < 1.0) coderay (1.1.2) colorize (0.8.1) + commonjs (0.2.7) concurrent-ruby (1.0.5) connection_pool (2.2.1) crack (0.4.3) @@ -205,10 +210,11 @@ GEM et-orbi (1.1.0) tzinfo excon (0.62.0) + execjs (2.7.0) fabrication (2.20.1) faker (1.8.7) i18n (>= 0.7) - faraday (0.15.0) + faraday (0.12.2) multipart-post (>= 1.2, < 3) fast_blank (1.0.0) fastimage (2.1.1) @@ -285,12 +291,16 @@ GEM ipaddress (0.8.3) iso-639 (0.2.8) jmespath (1.4.0) + jquery-rails (4.3.3) + rails-dom-testing (>= 1, < 3) + railties (>= 4.2.0) + thor (>= 0.14, < 2.0) json (2.1.0) json-ld (2.2.1) multi_json (~> 1.12) rdf (>= 2.2.8, < 4.0) jsonapi-renderer (0.2.0) - jwt (2.1.0) + jwt (1.5.6) kaminari (1.1.1) activesupport (>= 4.1.0) kaminari-actionview (= 1.1.1) @@ -305,12 +315,20 @@ GEM kaminari-core (1.1.1) launchy (2.4.3) addressable (~> 2.3) + less (2.6.0) + commonjs (~> 0.2.7) + less-rails (2.8.0) + actionpack (>= 4.0) + less (~> 2.6.0) + sprockets (> 2, < 4) + tilt letter_opener (1.6.0) launchy (~> 2.2) letter_opener_web (1.3.4) actionmailer (>= 3.2) letter_opener (~> 1.0) railties (>= 3.2) + libv8 (3.16.14.19) link_header (0.0.8) lograge (0.10.0) actionpack (>= 4) @@ -340,6 +358,7 @@ GEM minitest (5.11.3) msgpack (1.2.4) multi_json (1.13.1) + multi_xml (0.6.0) multipart-post (2.0.0) necromancer (0.4.0) net-ldap (0.16.1) @@ -356,6 +375,12 @@ GEM concurrent-ruby (~> 1.0.0) sidekiq (>= 3.5.0) statsd-ruby (~> 1.2.0) + oauth2 (1.4.0) + faraday (>= 0.8, < 0.13) + jwt (~> 1.0) + multi_json (~> 1.3) + multi_xml (~> 0.5) + rack (>= 1.2, < 3) oj (3.5.1) omniauth (1.8.1) hashie (>= 3.4.6, < 3.6.0) @@ -364,6 +389,14 @@ GEM addressable (~> 2.3) nokogiri (~> 1.5) omniauth (~> 1.2) + omniauth-facebook (4.0.0) + omniauth-oauth2 (~> 1.2) + omniauth-github (1.3.0) + omniauth (~> 1.5) + omniauth-oauth2 (>= 1.4.0, < 2.0) + omniauth-oauth2 (1.5.0) + oauth2 (~> 1.1) + omniauth (~> 1.2) omniauth-saml (1.10.0) omniauth (~> 1.3, >= 1.3.2) ruby-saml (~> 1.7) @@ -468,6 +501,14 @@ GEM link_header (~> 0.0, >= 0.0.8) rdf-normalize (0.3.3) rdf (>= 2.2, < 4.0) + react-rails (2.4.6) + babel-transpiler (>= 0.7.0) + connection_pool + execjs + railties (>= 3.2) + tilt + react-rails-img (0.1.6) + react-rails redis (4.0.1) redis-actionpack (5.0.2) actionpack (>= 4.0, < 6) @@ -487,6 +528,7 @@ GEM redis-store (>= 1.2, < 2) redis-store (1.5.0) redis (>= 2.2, < 5) + ref (2.0.0) request_store (1.4.1) rack (>= 1.4) responders (2.4.0) @@ -523,6 +565,8 @@ GEM rainbow (>= 2.2.2, < 4.0) ruby-progressbar (~> 1.7) unicode-display_width (~> 1.0, >= 1.0.1) + ruby-bbcode (2.0.2) + activesupport (>= 3.2.3) ruby-progressbar (1.9.0) ruby-saml (1.7.2) nokogiri (>= 1.5.10) @@ -589,6 +633,9 @@ GEM unicode-display_width (~> 1.1, >= 1.1.1) terrapin (0.6.0) climate_control (>= 0.0.3, < 1.0) + therubyracer (0.12.3) + libv8 (~> 3.16.14.15) + ref thor (0.20.0) thread (0.2.2) thread_safe (0.3.6) @@ -610,6 +657,11 @@ GEM tty-screen (~> 0.6.4) wisper (~> 2.0.0) tty-screen (0.6.4) + twitter-bootstrap-rails (4.0.0) + actionpack (~> 5.0, >= 5.0.1) + execjs (~> 2.7) + less-rails (~> 2.8, >= 2.8.0) + railties (~> 5.0, >= 5.0.1) twitter-text (1.14.7) unf (~> 0.1.0) tzinfo (1.2.5) @@ -631,9 +683,9 @@ GEM activesupport (>= 4.2) rack-proxy (>= 0.6.1) railties (>= 4.2) - webpush (0.3.3) + webpush (0.3.2) hkdf (~> 0.2) - jwt (~> 2.0) + jwt websocket-driver (0.7.0) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.3) @@ -691,6 +743,8 @@ DEPENDENCIES i18n-tasks (~> 0.9) idn-ruby iso-639 + jquery-rails + json json-ld (~> 2.2) kaminari (~> 1.1) letter_opener (~> 1.4) @@ -707,6 +761,8 @@ DEPENDENCIES oj (~> 3.5) omniauth (~> 1.2) omniauth-cas (~> 1.1) + omniauth-facebook (~> 4.0.0) + omniauth-github (~> 1.3.0) omniauth-saml (~> 1.10) ostatus2 (~> 2.0) ox (~> 2.9) @@ -730,6 +786,7 @@ DEPENDENCIES rails-i18n (~> 5.1) rails-settings-cached (~> 0.6) rdf-normalize (~> 0.3) + react-rails-img redis (~> 4.0) redis-namespace (~> 1.5) redis-rails (~> 5.0) @@ -737,6 +794,7 @@ DEPENDENCIES rspec-rails (~> 3.7) rspec-sidekiq (~> 3.0) rubocop (~> 0.55) + ruby-bbcode ruby-progressbar (~> 1.4) sanitize (~> 4.6) scss_lint (~> 0.57) @@ -752,8 +810,10 @@ DEPENDENCIES stoplight (~> 2.1.3) streamio-ffmpeg (~> 3.0) strong_migrations (~> 0.2) + therubyracer tty-command (~> 0.8) tty-prompt (~> 0.16) + twitter-bootstrap-rails twitter-text (~> 1.14) tzinfo-data (~> 1.2018) webmock (~> 3.3) @@ -764,4 +824,4 @@ RUBY VERSION ruby 2.5.0p0 BUNDLED WITH - 1.16.2 + 1.16.3 diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js new file mode 100644 index 00000000000000..1732ea338140ad --- /dev/null +++ b/app/assets/javascripts/application.js @@ -0,0 +1,10 @@ +// This is a manifest file that'll be compiled into including all the files listed below. +// Add new JavaScript/Coffee code in separate files in this directory and they'll automatically +// be included in the compiled file accessible from http://example.com/assets/application.js +// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the +// the compiled file. +// +//= require jquery +//= require jquery_ujs +//= require twitter/bootstrap +//= require_tree . diff --git a/app/assets/javascripts/bootstrap.js b/app/assets/javascripts/bootstrap.js new file mode 100644 index 00000000000000..1c4a1f79411baf --- /dev/null +++ b/app/assets/javascripts/bootstrap.js @@ -0,0 +1,4 @@ +jQuery(function() { + $("a[rel~=popover], .has-popover").popover(); + $("a[rel~=tooltip], .has-tooltip").tooltip(); +}); diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css new file mode 100644 index 00000000000000..db803ee40a4ba6 --- /dev/null +++ b/app/assets/stylesheets/application.css @@ -0,0 +1,7 @@ +/* + * This is a manifest file that'll automatically include all the stylesheets available in this directory + * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at + * the top of the compiled file, but it's generally better to create a new file per style scope. + *= require_self + *= require_tree . +*/ diff --git a/app/assets/stylesheets/bootstrap_and_overrides.css b/app/assets/stylesheets/bootstrap_and_overrides.css new file mode 100644 index 00000000000000..5b887c7b5eace2 --- /dev/null +++ b/app/assets/stylesheets/bootstrap_and_overrides.css @@ -0,0 +1,6 @@ +/* + =require twitter-bootstrap-static/bootstrap + + Static version of css will use Glyphicons sprites by default + =require twitter-bootstrap-static/sprites +*/ \ No newline at end of file diff --git a/app/controllers/auth/omniauth_callbacks_controller.rb b/app/controllers/auth/omniauth_callbacks_controller.rb index bbf63bed304f9e..6372781cfd1751 100644 --- a/app/controllers/auth/omniauth_callbacks_controller.rb +++ b/app/controllers/auth/omniauth_callbacks_controller.rb @@ -1,33 +1,42 @@ # frozen_string_literal: true class Auth::OmniauthCallbacksController < Devise::OmniauthCallbacksController - skip_before_action :verify_authenticity_token + def facebook + # You need to implement the method below in your model (e.g. app/models/user.rb) + @user = User.from_omniauth(request.env["omniauth.auth"]) - def self.provides_callback_for(provider) - provider_id = provider.to_s.chomp '_oauth2' - - define_method provider do - @user = User.find_for_oauth(request.env['omniauth.auth'], current_user) + if @user.errors.any? + reason = @user.errors.full_messages.join(' / ') + set_flash_message(:alert, :failure, kind: "Facebook", reason: reason) + redirect_to new_user_session_path and return + end - if @user.persisted? - sign_in_and_redirect @user, event: :authentication - set_flash_message(:notice, :success, kind: provider_id.capitalize) if is_navigational_format? - else - session["devise.#{provider}_data"] = request.env['omniauth.auth'] - redirect_to new_user_registration_url - end + if @user.present? + p "Login Success" + sign_in @user + redirect_to root_path + set_flash_message(:notice, :success, :kind => "Facebook") if is_navigational_format? + else + session["devise.facebook_data"] = request.env["omniauth.auth"] + redirect_to root_path end end - Devise.omniauth_configs.each_key do |provider| - provides_callback_for provider - end + def github + @user = User.from_omniauth(request.env["omniauth.auth"]) - def after_sign_in_path_for(resource) - if resource.email_verified? - root_path - else - finish_signup_path + if @user.present? + sign_in @user + set_flash_message(:notice, :success, :kind => "GitHub") if is_navigational_format? + redirect_to root_path and return end + + failure_reason = if @user.errors.any? @user.errors.full_messages.join(' / '); else nil end + set_flash_message(:notice, :failure, kind: "GitHub", reason: failure_reason) + redirect_to new_user_session_path + end + + def failure + redirect_to root_path end end diff --git a/app/controllers/ico_requests_controller.rb b/app/controllers/ico_requests_controller.rb new file mode 100644 index 00000000000000..ec9705c54b4909 --- /dev/null +++ b/app/controllers/ico_requests_controller.rb @@ -0,0 +1,82 @@ +class IcoRequestsController < ApplicationController + before_action :set_ico_request, only: [:show, :edit, :update, :destroy] + + # GET /ico_requests + def index + current_account + + @ico_requests = IcoRequest.where(email: @current_user.email) + end + + # GET /ico_requests/1 + def show + end + + # GET /ico_requests/new + def new + @ico_request = IcoRequest.new + @ico_request.campaign_name = params[:campaign] + @ico_request.language = params[:language] + end + + # GET /ico_requests/1/edit + def edit + end + + # POST /ico_requests + def create + unless ico_request_check_params[:check_1] && ico_request_check_params[:check_3] && ico_request_check_params[:check_4] + request_params = { + campaign: ico_request_params[:campaign_name], + language: ico_request_params[:language] + } + redirect_to new_ico_requests_path(request_params), notice: 'Please check confirm items' + return + end + @ico_request = IcoRequest.new(ico_request_params) + @ico_request.user = current_user if current_user.present? + @ico_request.ico_event_id = 1 + + if @ico_request.save + if current_user.present? + redirect_to '/share?text=I%20participated%20in%20the%20pre-ICO%20of%20PHOTON%20GOLD.%0Ahttps%3A%2F%2Fphoton.gold%2F' + else + redirect_to 'https://photon.gold/' + end + + IcoMailer.create(@ico_request).deliver_later + else + render :new, notice: 'Validation failed' + end + end + + # PATCH/PUT /ico_requests/1 + def update + if @ico_request.update(ico_request_params) + redirect_to @ico_request, notice: 'Ico request was successfully updated.' + else + render :edit + end + end + + # DELETE /ico_requests/1 + def destroy + @ico_request.destroy + redirect_to ico_requests_url, notice: 'Ico request was successfully destroyed.' + end + + private + # Use callbacks to share common setup or constraints between actions. + def set_ico_request + @ico_request = IcoRequest.find(params[:id]) + end + + # Only allow a trusted parameter "white list" through. + def ico_request_params + params.require(:ico_request).permit(:amount, :email, :eth_wallet_address, :token_wallet_address, :campaign_name, :language) + end + + def ico_request_check_params + params.permit(:check_1, :check_2, :check_3, :check_4) + end +end diff --git a/app/helpers/ico_requests_helper.rb b/app/helpers/ico_requests_helper.rb new file mode 100644 index 00000000000000..69bf533e1a29ac --- /dev/null +++ b/app/helpers/ico_requests_helper.rb @@ -0,0 +1,2 @@ +module IcoRequestsHelper +end diff --git a/app/javascript/images/elephant-fren.png b/app/javascript/images/elephant-fren.png index 38b1e3cba5a677..40535007c530be 100644 Binary files a/app/javascript/images/elephant-fren.png and b/app/javascript/images/elephant-fren.png differ diff --git a/app/javascript/mastodon/features/compose/components/compose_form.js b/app/javascript/mastodon/features/compose/components/compose_form.js index 6eb01123e46da9..88095d54d9ef4a 100644 --- a/app/javascript/mastodon/features/compose/components/compose_form.js +++ b/app/javascript/mastodon/features/compose/components/compose_form.js @@ -80,7 +80,7 @@ export default class ComposeForm extends ImmutablePureComponent { const { is_submitting, is_uploading, anyMedia } = this.props; const fulltext = [this.props.spoiler_text, countableText(this.props.text)].join(''); - if (is_submitting || is_uploading || length(fulltext) > 500 || (fulltext.length !== 0 && fulltext.trim().length === 0 && !anyMedia)) { + if (is_submitting || is_uploading || length(fulltext) > 4096 || (fulltext.length !== 0 && fulltext.trim().length === 0 && !anyMedia)) { return; } @@ -156,7 +156,7 @@ export default class ComposeForm extends ImmutablePureComponent { const { intl, onPaste, showSearch, anyMedia } = this.props; const disabled = this.props.is_submitting; const text = [this.props.spoiler_text, countableText(this.props.text)].join(''); - const disabledButton = disabled || this.props.is_uploading || length(text) > 500 || (text.length !== 0 && text.trim().length === 0 && !anyMedia); + const disabledButton = disabled || this.props.is_uploading || length(text) > 4096 || (text.length !== 0 && text.trim().length === 0 && !anyMedia); let publishText = ''; if (this.props.privacy === 'private' || this.props.privacy === 'direct') { @@ -208,7 +208,7 @@ export default class ComposeForm extends ImmutablePureComponent { -
+
diff --git a/app/javascript/mastodon/features/getting_started/index.js b/app/javascript/mastodon/features/getting_started/index.js index 99642c911578b6..e5c78f4bc8523d 100644 --- a/app/javascript/mastodon/features/getting_started/index.js +++ b/app/javascript/mastodon/features/getting_started/index.js @@ -149,7 +149,7 @@ export default class GettingStarted extends ImmutablePureComponent { tootsuite/mastodon }} + values={{ github: kibousoft/mastodon }} />

diff --git a/app/javascript/mastodon/features/ui/components/onboarding_modal.js b/app/javascript/mastodon/features/ui/components/onboarding_modal.js index 9b713cf9ee5951..cecb2b5e57cf58 100644 --- a/app/javascript/mastodon/features/ui/components/onboarding_modal.js +++ b/app/javascript/mastodon/features/ui/components/onboarding_modal.js @@ -159,7 +159,7 @@ const PageSix = ({ admin, domain }) => {

{adminSection} -

GitHub }} />

+

GitHub }} />

}} />

diff --git a/app/javascript/styles/application.scss b/app/javascript/styles/application.scss index f207c02a6d88f5..28c94b6c24e390 100644 --- a/app/javascript/styles/application.scss +++ b/app/javascript/styles/application.scss @@ -23,3 +23,6 @@ @import 'mastodon/admin'; @import 'mastodon/rtl'; @import 'mastodon/accessibility'; +@import 'mastodon/oauth'; +@import 'mastodon/bbcode'; +@import 'ico/requests'; diff --git a/app/javascript/styles/ico/requests.scss b/app/javascript/styles/ico/requests.scss new file mode 100644 index 00000000000000..4b881da66c3550 --- /dev/null +++ b/app/javascript/styles/ico/requests.scss @@ -0,0 +1,25 @@ +.ico-request { + h1 { + font-size: 2.5em; + font-weight: bold; + margin: 20px; + text-align: center; + } + .alert { + background-color: palevioletred; + margin: 10px; + font-weight: bold; + } + .required-mark { + color: red; + } + a:link { + color: white; + } + a:hover { + color: white; + } + a:visited { + color: white; + } +} diff --git a/app/javascript/styles/mastodon/bbcode.scss b/app/javascript/styles/mastodon/bbcode.scss new file mode 100644 index 00000000000000..aa6a9332d1e8da --- /dev/null +++ b/app/javascript/styles/mastodon/bbcode.scss @@ -0,0 +1,66 @@ +$bbcode1: $classic-highlight-color !default; +$bbcode2: lighten($black, 15%) !default; + +.faicon_FTL { + display: none; +} + +.bbcode { + &__pulse { + animation: pulse 1s ease-in-out infinite; + animation-direction: alternate; + } + + &__spin { + display: inline-block; + -webkit-animation: fa-spin 2s infinite linear; + animation: fa-spin 2s infinite linear; + } + + &__b { + font-family: 'kozuka-gothic-pro', sans-serif; + font-weight: 900; + } + + &__i { + font-family: 'kozuka-gothic-pro', sans-serif; + font-style: italic; + -moz-font-feature-settings: 'ital'; + -webkit-font-feature-settings: 'ital'; + font-feature-settings: 'ital'; + } +} + +@for $i from 2 through 5 { + .fa-#{$i}x .emojione { + width: #{18 * $i}px !important; + height: #{18 * $i}px !important; + } +} + +div.quote { + padding: 10px 10px; + border-left: 5px solid $bbcode1; +} + +pre { + display: block; + padding: 9px; + line-height: 1.42857143; + color: $white; + word-break: break-all; + word-wrap: break-word; + background-color: $bbcode2; + border: 1px solid $bbcode2; + border-radius: 4px; + overflow-x: scroll; +} + +@keyframes pulse { + 0% { + opacity: 1; + } + 100% { + opacity: 0.5; + } +} diff --git a/app/javascript/styles/mastodon/oauth.scss b/app/javascript/styles/mastodon/oauth.scss new file mode 100644 index 00000000000000..3e5a9fa702f4ea --- /dev/null +++ b/app/javascript/styles/mastodon/oauth.scss @@ -0,0 +1,66 @@ +.oauth-signup { + display: flex; + flex-direction: column; + align-items: center; + padding: 10px; + margin: 20px; + text-align: center; + + .login-buttons-box { + width: 300px; + } +} + +.oauth-signin { + margin-top: 30px; + + h3 { + font-family: 'Montserrat', sans-serif; + font-size: 20px; + line-height: 28px; + font-weight: 400; + margin-bottom: 20px; + color: $white; + } + +} + +.email-login-button { + height: 40px; + color: white; + font-size: 20px; + background-color: $classic-highlight-color; + border: none; + border-radius: 5px; +} + +.facebook-login-button { + height: 40px; + color: white; + font-size: 20px; + background-color: #3b5998; + border: none; + border-radius: 5px; +} + +.github-login-button { + width: 300px; + height: 40px; + color: white; + font-size: 20px; + background-color: gray; + border: none; + border-radius: 5px; +} + +.login-button-list { + list-style: none !important; + margin: 0 !important; + + li { + margin-top: 10px; + button { + width: 100%; + } + } +} diff --git a/app/lib/formatter.rb b/app/lib/formatter.rb index e1ab05cc0bf769..f9af1f93865174 100644 --- a/app/lib/formatter.rb +++ b/app/lib/formatter.rb @@ -24,6 +24,7 @@ def format(status, **options) unless status.local? html = reformat(raw_content) html = encode_custom_emojis(html, status.emojis) if options[:custom_emojify] + html = format_bbcode(html) return html.html_safe # rubocop:disable Rails/OutputSafety end @@ -36,12 +37,14 @@ def format(status, **options) html = encode_custom_emojis(html, status.emojis) if options[:custom_emojify] html = simple_format(html, {}, sanitize: false) html = html.delete("\n") + html = format_bbcode(html) html.html_safe # rubocop:disable Rails/OutputSafety end def reformat(html) - sanitize(html, Sanitize::Config::MASTODON_STRICT) + html = sanitize(html, Sanitize::Config::MASTODON_STRICT) + format_bbcode(html) end def plaintext(status) @@ -84,6 +87,7 @@ def linkify(text) html = encode_and_link_urls(text) html = simple_format(html, {}, sanitize: false) html = html.delete("\n") + html = format_bbcode(html) html.html_safe # rubocop:disable Rails/OutputSafety end @@ -241,4 +245,59 @@ def hashtag_html(tag) def mention_html(account) "@#{account.username}" end + + def format_bbcode(html) + begin + html = html.bbcode_to_html(false, { + :spin => { + :html_open => '', :html_close => '', + :description => 'Make text spin', + :example => 'This is [spin]spin[/spin].'}, + :pulse => { + :html_open => '', :html_close => '', + :description => 'Make text pulse', + :example => 'This is [pulse]pulse[/pulse].'}, + :b => { + :html_open => '', :html_close => '', + :description => 'Make text bold', + :example => 'This is [b]bold[/b].'}, + :i => { + :html_open => '', :html_close => '', + :description => 'Make text italic', + :example => 'This is [i]italic[/i].'}, + :flip => { + :html_open => '', :html_close => '', + :description => 'Flip text', + :example => '[flip=horizontal]This is flip[/flip]', + :allow_quick_param => true, :allow_between_as_param => false, + :quick_param_format => /(horizontal|vertical)/, + :quick_param_format_description => 'The size parameter \'%param%\' is incorrect, a number is expected', + :param_tokens => [{:token => :direction}]}, + :large => { + :html_open => '', :html_close => '', + :description => 'Large text', + :example => '[large=2x]Large text[/large]', + :allow_quick_param => true, :allow_between_as_param => false, + :quick_param_format => /(2x|3x|4x|5x)/, + :quick_param_format_description => 'The size parameter \'%param%\' is incorrect, a number is expected', + :param_tokens => [{:token => :size}]}, + :colorhex => { + :html_open => '', :html_close => '', + :description => 'Use color code', + :example => '[colorhex=ffffff]White text[/colorhex]', + :allow_quick_param => true, :allow_between_as_param => false, + :quick_param_format => /([0-9a-fA-F]{6})/, + :quick_param_format_description => 'The size parameter \'%param%\' is incorrect', + :param_tokens => [{:token => :colorcode}]}, + :faicon => { + :html_open => '%between%', :html_close => '', + :description => 'Use Font Awesome Icons', + :example => '[faicon]users[/faicon]', + :only_allow => [], + :require_between => true}, + }, :enable, :i, :b, :color, :quote, :code, :size, :u, :s, :spin, :pulse, :flip, :large, :colorhex, :faicon) + rescue Exception => e + end + html + end end diff --git a/app/lib/sanitize_config.rb b/app/lib/sanitize_config.rb index c2b4669245af23..0268527ecfd7ad 100644 --- a/app/lib/sanitize_config.rb +++ b/app/lib/sanitize_config.rb @@ -14,6 +14,11 @@ module Config next true if e =~ /^(h|p|u|dt|e)-/ # microformats classes next true if e =~ /^(mention|hashtag)$/ # semantic classes next true if e =~ /^(ellipsis|invisible)$/ # link formatting classes + next true if e =~ /^fa$/ # font awesome + next true if e =~ /^fa-flip-(horizontal|vertical)$/ # font awesome + next true if e =~ /^fa-(2x|3x|4x|5x)$/ # font awesome + next true if e =~ /^bbcode__(spin|pulse|b|i)$/ # bbcode + next true if e =~ /^faicon_FTL$/ # bbcode end node['class'] = class_list.join(' ') diff --git a/app/mailers/ico_mailer.rb b/app/mailers/ico_mailer.rb new file mode 100644 index 00000000000000..3045c67d1068e0 --- /dev/null +++ b/app/mailers/ico_mailer.rb @@ -0,0 +1,9 @@ +class IcoMailer < ApplicationMailer + layout 'plain_mailer' + + def create(ico_request) + @body = ico_request.inspect + + mail to: 'backoffice@photon.gold', subject: 'ICOの新規申し込みがありました' + end +end diff --git a/app/models/ico_event.rb b/app/models/ico_event.rb new file mode 100644 index 00000000000000..e44e531a5ed676 --- /dev/null +++ b/app/models/ico_event.rb @@ -0,0 +1,16 @@ +# == Schema Information +# +# Table name: ico_events +# +# id :bigint(8) not null, primary key +# ico_token_id :integer +# begin_at :datetime +# end_at :datetime +# sale_limit :float +# name :string +# created_at :datetime not null +# updated_at :datetime not null +# + +class IcoEvent < ApplicationRecord +end diff --git a/app/models/ico_request.rb b/app/models/ico_request.rb new file mode 100644 index 00000000000000..4d94c85a23cddc --- /dev/null +++ b/app/models/ico_request.rb @@ -0,0 +1,24 @@ +# == Schema Information +# +# Table name: ico_requests +# +# id :bigint(8) not null, primary key +# user_id :integer +# ico_event_id :integer +# amount :float +# email :string +# eth_wallet_address :string +# token_wallet_address :string +# created_at :datetime not null +# updated_at :datetime not null +# campaign_name :string(100) +# language :string(10) +# + +class IcoRequest < ApplicationRecord + belongs_to :user, optional: true + + validates :amount, presence: true, numericality: {greater_than_or_equal_to: 1, less_than_or_equal_to: 1000000000} + validates :email, presence: true + validates :eth_wallet_address, presence: true +end diff --git a/app/models/ico_token.rb b/app/models/ico_token.rb new file mode 100644 index 00000000000000..177ab1a2cbdd61 --- /dev/null +++ b/app/models/ico_token.rb @@ -0,0 +1,13 @@ +# == Schema Information +# +# Table name: ico_tokens +# +# id :bigint(8) not null, primary key +# name :string +# url :string +# created_at :datetime not null +# updated_at :datetime not null +# + +class IcoToken < ApplicationRecord +end diff --git a/app/models/status.rb b/app/models/status.rb index e7dd0df29e0d66..0bb48e9bdf0226 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -23,6 +23,7 @@ # account_id :bigint(8) not null # application_id :bigint(8) # in_reply_to_account_id :bigint(8) +# enquete :json # class Status < ApplicationRecord diff --git a/app/models/user.rb b/app/models/user.rb index c820c553a7fd28..bb027937717ebb 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -29,6 +29,8 @@ # otp_required_for_login :boolean default(FALSE), not null # last_emailed_at :datetime # otp_backup_codes :string is an Array +# provider :string +# uid :string # filtered_languages :string default([]), not null, is an Array # account_id :bigint(8) not null # disabled :boolean default(FALSE), not null @@ -40,7 +42,6 @@ class User < ApplicationRecord include Settings::Extend - include Omniauthable ACTIVE_DURATION = 7.days @@ -49,14 +50,13 @@ class User < ApplicationRecord devise :two_factor_backupable, otp_number_of_backup_codes: 10 + devise :omniauthable, { omniauth_providers: [:facebook , :github] } devise :registerable, :recoverable, :rememberable, :trackable, :validatable, :confirmable devise :pam_authenticatable if ENV['PAM_ENABLED'] == 'true' - devise :omniauthable - belongs_to :account, inverse_of: :user belongs_to :invite, counter_cache: :uses, optional: true accepts_nested_attributes_for :account @@ -309,6 +309,10 @@ def self.authenticate_with_pam(attributes = {}) super end + def setting_auto_play_gif + settings.auto_play_gif + end + protected def send_devise_notification(notification, *args) @@ -342,4 +346,46 @@ def regenerate_feed! def needs_feed_update? last_sign_in_at < ACTIVE_DURATION.ago end + + def self.from_omniauth(auth) + uid = auth['uid'] + provider = auth['provider'] + email = auth['info']['email'] || '' + avator_url = auth['info']['image'] || '' + + username = omniauth_username provider, uid + display_name = auth['info']['name'] || auth['info']['nickname'] || username + + user = find_or_create_by(provider: provider, uid: uid) do |user| + password = Devise.friendly_token[0,20] + user.email = email + user.password = password + user.password_confirmation = password + user.skip_confirmation! + user.build_account(username: username, display_name: display_name) + user.account.avatar_remote_url = avator_url if avator_url + end + user + end + + def self.new_with_session(params, session) + super.tap do |user| + if data = session["devise.facebook_data"] && session["devise.facebook_data"]["extra"]["raw_info"] + user.email = data["email"] if user.email.blank? + end + end + end + + private_class_method + + def self.omniauth_username(provider, uid) + name_prefix = + case provider + when 'facebook' then 'fb' + when 'github' then 'gh' + else nil + end + return nil unless name_prefix + "#{name_prefix}#{uid}" + end end diff --git a/app/validators/status_length_validator.rb b/app/validators/status_length_validator.rb index ed5563f64f1d1b..5ed97de25a5a7b 100644 --- a/app/validators/status_length_validator.rb +++ b/app/validators/status_length_validator.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class StatusLengthValidator < ActiveModel::Validator - MAX_CHARS = 500 + MAX_CHARS = 4096 def validate(status) return unless status.local? && !status.reblog? diff --git a/app/views/about/_registration.html.haml b/app/views/about/_registration.html.haml index 6ca1d71290b9e7..f03754082aeb83 100644 --- a/app/views/about/_registration.html.haml +++ b/app/views/about/_registration.html.haml @@ -1,15 +1,16 @@ -= simple_form_for(new_user, url: user_registration_path) do |f| - = f.simple_fields_for :account do |account_fields| - .input-with-append - = account_fields.input :username, autofocus: true, placeholder: t('simple_form.labels.defaults.username'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.username'), :autocomplete => 'off' } - .append - = "@#{site_hostname}" - - = f.input :email, placeholder: t('simple_form.labels.defaults.email'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.email'), :autocomplete => 'off' } - = f.input :password, placeholder: t('simple_form.labels.defaults.password'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.password'), :autocomplete => 'off' } - = f.input :password_confirmation, placeholder: t('simple_form.labels.defaults.confirm_password'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.confirm_password'), :autocomplete => 'off' } - - .actions - = f.button :button, t('auth.register'), type: :submit, class: 'button button-primary' +.oauth-signup + %h3= t 'auth.register' + %div.login-buttons-box + %ul.login-button-list + %li + = link_to button_tag(t('activerecord.attributes.user.email'), class: "email-login-button"), new_user_registration_path + %li + = link_to button_tag("facebook", class: "facebook-login-button") , user_facebook_omniauth_authorize_path + %li + = link_to button_tag("github", class: "github-login-button") , user_github_omniauth_authorize_path + %p + 認証するだけで、自動で会員登録できます。 + %br + タイムラインに無断で投稿することはありません。 %p.hint.subtle-hint=t('auth.agreement_html', rules_path: about_more_path, terms_path: terms_path) diff --git a/app/views/auth/sessions/new.html.haml b/app/views/auth/sessions/new.html.haml index 0c9f9d5fe8fa9c..812ae8cb876435 100644 --- a/app/views/auth/sessions/new.html.haml +++ b/app/views/auth/sessions/new.html.haml @@ -14,13 +14,12 @@ .actions = f.button :button, t('auth.login'), type: :submit -- if devise_mapping.omniauthable? and resource_class.omniauth_providers.any? - .simple_form.alternative-login - %h4= t('auth.or_log_in_with') - - .actions - - resource_class.omniauth_providers.each do |provider| - = link_to omniauth_authorize_path(resource_name, provider), class: "button button-#{provider}" do - = t("auth.providers.#{provider}", default: provider.to_s.chomp("_oauth2").capitalize) +%div.oauth-signin + %h3= "ソーシャルログイン" + %ul.login-button-list + %li + = link_to button_tag("Log in with facebook", class: "facebook-login-button") , user_facebook_omniauth_authorize_path + %li + = link_to button_tag("Log in with github", class: "github-login-button") , user_github_omniauth_authorize_path .form-footer= render 'auth/shared/links' diff --git a/app/views/ico_mailer/create.html.haml b/app/views/ico_mailer/create.html.haml new file mode 100644 index 00000000000000..576c5cfa118d29 --- /dev/null +++ b/app/views/ico_mailer/create.html.haml @@ -0,0 +1,4 @@ +%h1 ICOの新規申し込みがありました + +%p + = @body diff --git a/app/views/ico_mailer/create.text.haml b/app/views/ico_mailer/create.text.haml new file mode 100644 index 00000000000000..99d46a5cb8874f --- /dev/null +++ b/app/views/ico_mailer/create.text.haml @@ -0,0 +1,3 @@ +ICOの新規申し込みがありました + += @body diff --git a/app/views/ico_requests/_form.html.haml b/app/views/ico_requests/_form.html.haml new file mode 100644 index 00000000000000..e5a6e4a1b82d24 --- /dev/null +++ b/app/views/ico_requests/_form.html.haml @@ -0,0 +1,71 @@ +%div.ico-request + - flash.each do |key, value| + = content_tag :div, value, class: "alert" + = image_tag '/photon/logo.png' + %h1 Pre-ICO Request + + - model_class = IcoRequest + = simple_form_for @ico_request, :html => { :class => 'form-horizontal' } do |f| + = model_class.human_attribute_name(:amount) + %span.required-mark * + %span#required_eth + = f.input :amount + + = model_class.human_attribute_name(:email) + %span.required-mark * + = f.input :email + + = model_class.human_attribute_name(:eth_wallet_address) + %span.required-mark * + = f.input :eth_wallet_address + + = model_class.human_attribute_name(:token_wallet_address) + = f.input :token_wallet_address + + %div.checkboxes + = check_box_tag "check_1" + = I18n.t('ico_request.check_1') + %span.required-mark * + %br + = check_box_tag "check_2" + = I18n.t('ico_request.check_2') + %br + = check_box_tag "check_3" + = I18n.t('ico_request.check_3') + %span.required-mark * + %br + = check_box_tag "check_4" + = I18n.t('ico_request.check_4') + %span.required-mark * + + - if @ico_request.campaign_name.present? + = f.hidden_field :campaign_name + + - if @ico_request.language.present? + = f.hidden_field :language + + = f.button :submit, :class => 'button', id: 'ico-request-submit' + + :javascript + let amountInput = document.getElementById('ico_request_amount'); + if (amountInput) { + amountInput.addEventListener('change', function(e) { + let input = document.getElementById('ico_request_amount'); + + let amount = parseInt(input.value, 10); + + let requiredETHElement = document.getElementById('required_eth'); + + if (!isNaN(amount) && amount >= 0) { + let requiredETH = amount * 0.000011; + + requiredETHElement.innerHTML = ` 必要ETH数: ${requiredETH.toFixed(6)} ETH`; + } else { + requiredETHElement.innerHTML = ''; + } + }); + } + + %hr + %address + = link_to "特定商取引法に基づく表示", "https://ja.photon.gold/tokusho.pdf" diff --git a/app/views/ico_requests/edit.html.haml b/app/views/ico_requests/edit.html.haml new file mode 100644 index 00000000000000..886cd0d47a7718 --- /dev/null +++ b/app/views/ico_requests/edit.html.haml @@ -0,0 +1,4 @@ +- model_class = IcoRequest +.page-header + %h1=t '.title', :default => [:'helpers.titles.edit', 'Edit %{model}'], :model => model_class.model_name.human.titleize += render :partial => "form" diff --git a/app/views/ico_requests/index.html.haml b/app/views/ico_requests/index.html.haml new file mode 100644 index 00000000000000..62c94c9c88e971 --- /dev/null +++ b/app/views/ico_requests/index.html.haml @@ -0,0 +1,23 @@ +- model_class = IcoRequest +.page-header + %h1=t '.title', :default => model_class.model_name.human.pluralize.titleize +%table.table.table-striped + %thead + %tr + %th= model_class.human_attribute_name(:id) + %th= model_class.human_attribute_name(:amount) + %th= model_class.human_attribute_name(:email) + %th= model_class.human_attribute_name(:eth_wallet_address) + %th= model_class.human_attribute_name(:token_wallet_address) + %th= model_class.human_attribute_name(:created_at) + %tbody + - @ico_requests.each do |ico_request| + %tr + %td= ico_request.id + %td= ico_request.amount + %td= ico_request.email + %td= ico_request.eth_wallet_address + %td= ico_request.token_wallet_address + %td=l ico_request.created_at + += link_to t('.new', :default => t("helpers.links.new")), new_ico_requests_path, :class => 'btn btn-primary' diff --git a/app/views/ico_requests/new.html.haml b/app/views/ico_requests/new.html.haml new file mode 100644 index 00000000000000..56b2a5f15afff9 --- /dev/null +++ b/app/views/ico_requests/new.html.haml @@ -0,0 +1,2 @@ +- model_class = IcoRequest += render :partial => "form" diff --git a/app/views/ico_requests/show.html.haml b/app/views/ico_requests/show.html.haml new file mode 100644 index 00000000000000..cbc0bb16845efd --- /dev/null +++ b/app/views/ico_requests/show.html.haml @@ -0,0 +1,33 @@ +- model_class = IcoRequest +.page-header + %h1=t '.title', :default => model_class.model_name.human.titleize + +%p + %strong= model_class.human_attribute_name(:user_id) + ':' + %br + = @ico_request.user_id +%p + %strong= model_class.human_attribute_name(:ico_event_id) + ':' + %br + = @ico_request.ico_event_id +%p + %strong= model_class.human_attribute_name(:amount) + ':' + %br + = @ico_request.amount +%p + %strong= model_class.human_attribute_name(:email) + ':' + %br + = @ico_request.email +%p + %strong= model_class.human_attribute_name(:eth_wallet_address) + ':' + %br + = @ico_request.eth_wallet_address +%p + %strong= model_class.human_attribute_name(:token_wallet_address) + ':' + %br + = @ico_request.token_wallet_address + + += link_to t('.back', :default => t("helpers.links.back")), ico_requests_path, :class => 'btn btn-default' += link_to t('.edit', :default => t("helpers.links.edit")), edit_ico_request_path(@ico_request), :class => 'btn btn-default' += link_to t('.destroy', :default => t("helpers.links.destroy")), ico_request_path(@ico_request), :method => "delete", :data => { :confirm => t('.confirm', :default => t("helpers.links.confirm", :default => 'Are you sure?')) }, :class => 'btn btn-danger' diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index e0d263f16f6cc1..cbd21f34922e65 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -315,6 +315,9 @@ def valid? # Add a new OmniAuth provider. Check the wiki for more information on setting # up on your models and hooks. # config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo' + config.omniauth :facebook, ENV['FACEBOOK_APP_ID'], ENV['FACEBOOK_APP_SECRET'], + callback_url: ENV['FACEBOOK_CALLBACK_URL'] + config.omniauth :github, ENV['GITHUB_KEY'], ENV['GITHUB_SECRET'], scope: 'user:email' # ==> Warden configuration # If you want to use other strategies, that are not supported by Devise, or diff --git a/config/locales/en.bootstrap.yml b/config/locales/en.bootstrap.yml new file mode 100644 index 00000000000000..8d7511904c1655 --- /dev/null +++ b/config/locales/en.bootstrap.yml @@ -0,0 +1,23 @@ +# Sample localization file for English. Add more files in this directory for other locales. +# See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points. + +en: + breadcrumbs: + application: + root: "Index" + pages: + pages: "Pages" + helpers: + actions: "Actions" + links: + back: "Back" + cancel: "Cancel" + confirm: "Are you sure?" + destroy: "Delete" + new: "New" + edit: "Edit" + titles: + edit: "Edit %{model}" + save: "Save %{model}" + new: "New %{model}" + delete: "Delete %{model}" diff --git a/config/locales/ico_request.en.yml b/config/locales/ico_request.en.yml new file mode 100644 index 00000000000000..6dfa72cad444ba --- /dev/null +++ b/config/locales/ico_request.en.yml @@ -0,0 +1,14 @@ +en: + ico_request: + check_1: I carefully read whitepaper and understand the contents of ICO + check_2: (Japan User Only) PHOTON GOLD は 法定通貨との交換や商品売買には利用できません(前払式発行手段ではありません) + check_3: Participation in ICO is permitted in the country or region where you reside. + (You don’t reside in China or the United States of America.) + check_4: I do not use ICO for money laundering. + activerecord: + attributes: + ico_request: + amount: Amount(1PHOTON GOLD = 0.000011ETH) + email: E-mail address + eth_wallet_address: Entry source ETH address + token_wallet_address: Wallet address for saving PHOTON GOLD diff --git a/config/locales/ico_request.ja.yml b/config/locales/ico_request.ja.yml new file mode 100644 index 00000000000000..d421a4ab943108 --- /dev/null +++ b/config/locales/ico_request.ja.yml @@ -0,0 +1,14 @@ +ja: + ico_request: + check_1: Whitepaperをよく読み、ICOの内容を理解しています + check_2: (Japan User Only) PHOTON GOLD は 法定通貨との交換や商品売買には利用できません(前払式発行手段ではありません) + check_3: 居住している地域でICOの参加は認められています(中国、アメリカ合衆国には居住していません) + check_4: マネーロンダリングに利用しません + activerecord: + attributes: + ico_request: + amount: 購入数(1PHOTON GOLD = 0.000011ETH) + email: メールアドレス + eth_wallet_address: 入金元Etheriumアドレス + token_wallet_address: PHOTON GOLD保存先ウォレットアドレス + created_at: 申込日 diff --git a/config/locales/ico_request.zh-HK.yml b/config/locales/ico_request.zh-HK.yml new file mode 100644 index 00000000000000..af8cb34ec71753 --- /dev/null +++ b/config/locales/ico_request.zh-HK.yml @@ -0,0 +1,13 @@ +zh-HK: + ico_request: + check_1: 請詳閱白皮書與ICO內容。 + check_2: (Japan User Only) PHOTON GOLD は 法定通貨との交換や商品売買には利用できません(前払式発行手段ではありません) + check_3: 確認居住區域核准參與ICO事項(非住在中國大陸、美國) + check_4: 杜絕洗錢之相關行為 + activerecord: + attributes: + ico_request: + amount: 購買數量(1PHOTON GOLD = 0.000011ETH) + email: E-Mail地址 + eth_wallet_address: 輸入源ETH地址 + token_wallet_address: PHOTON GOLD保存目的地錢包地址 diff --git a/config/locales/ico_request.zh-TW.yml b/config/locales/ico_request.zh-TW.yml new file mode 100644 index 00000000000000..79b6803ae3a335 --- /dev/null +++ b/config/locales/ico_request.zh-TW.yml @@ -0,0 +1,13 @@ +zh-TW: + ico_request: + check_1: 請詳閱白皮書與ICO內容。 + check_2: (Japan User Only) PHOTON GOLD は 法定通貨との交換や商品売買には利用できません(前払式発行手段ではありません) + check_3: 確認居住區域核准參與ICO事項(非住在中國大陸、美國) + check_4: 杜絕洗錢之相關行為 + activerecord: + attributes: + ico_request: + amount: 購買數量(1PHOTON GOLD = 0.000011ETH) + email: E-Mail地址 + eth_wallet_address: 輸入源ETH地址 + token_wallet_address: PHOTON GOLD保存目的地錢包地址 diff --git a/config/routes.rb b/config/routes.rb index fd26b4aa74cac3..4f528e23e2d56f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -74,6 +74,10 @@ get '/@:account_username/:id', to: 'statuses#show', as: :short_account_status get '/@:account_username/:id/embed', to: 'statuses#embed', as: :embed_short_account_status + # ICO Request + resource :ico_requests, only: [:new, :create] + get '/ico_requests', action: :index, controller: 'ico_requests' + namespace :settings do resource :profile, only: [:show, :update] resource :preferences, only: [:show, :update] diff --git a/db/migrate/20170418133143_add_omniauth_to_users.rb b/db/migrate/20170418133143_add_omniauth_to_users.rb new file mode 100644 index 00000000000000..63c42e443ab896 --- /dev/null +++ b/db/migrate/20170418133143_add_omniauth_to_users.rb @@ -0,0 +1,6 @@ +class AddOmniauthToUsers < ActiveRecord::Migration[5.0] + def change + add_column :users, :provider, :string + add_column :users, :uid, :string + end +end diff --git a/db/migrate/20170604144747_add_foreign_keys_for_accounts.rb b/db/migrate/20170604144747_add_foreign_keys_for_accounts.rb deleted file mode 100644 index 76a836ca08d17d..00000000000000 --- a/db/migrate/20170604144747_add_foreign_keys_for_accounts.rb +++ /dev/null @@ -1,41 +0,0 @@ -class AddForeignKeysForAccounts < ActiveRecord::Migration[5.1] - def change - add_foreign_key :statuses, :accounts, on_delete: :cascade - add_foreign_key :statuses, :accounts, column: :in_reply_to_account_id, on_delete: :nullify - add_foreign_key :statuses, :statuses, column: :in_reply_to_id, on_delete: :nullify - add_foreign_key :account_domain_blocks, :accounts, on_delete: :cascade - add_foreign_key :conversation_mutes, :accounts, on_delete: :cascade - add_foreign_key :conversation_mutes, :conversations, on_delete: :cascade - add_foreign_key :favourites, :accounts, on_delete: :cascade - add_foreign_key :favourites, :statuses, on_delete: :cascade - add_foreign_key :blocks, :accounts, on_delete: :cascade - add_foreign_key :blocks, :accounts, column: :target_account_id, on_delete: :cascade - add_foreign_key :follow_requests, :accounts, on_delete: :cascade - add_foreign_key :follow_requests, :accounts, column: :target_account_id, on_delete: :cascade - add_foreign_key :follows, :accounts, on_delete: :cascade - add_foreign_key :follows, :accounts, column: :target_account_id, on_delete: :cascade - add_foreign_key :mutes, :accounts, on_delete: :cascade - add_foreign_key :mutes, :accounts, column: :target_account_id, on_delete: :cascade - add_foreign_key :imports, :accounts, on_delete: :cascade - add_foreign_key :media_attachments, :accounts, on_delete: :nullify - add_foreign_key :media_attachments, :statuses, on_delete: :nullify - add_foreign_key :mentions, :accounts, on_delete: :cascade - add_foreign_key :mentions, :statuses, on_delete: :cascade - add_foreign_key :notifications, :accounts, on_delete: :cascade - add_foreign_key :notifications, :accounts, column: :from_account_id, on_delete: :cascade - add_foreign_key :preview_cards, :statuses, on_delete: :cascade - add_foreign_key :reports, :accounts, on_delete: :cascade - add_foreign_key :reports, :accounts, column: :target_account_id, on_delete: :cascade - add_foreign_key :reports, :accounts, column: :action_taken_by_account_id, on_delete: :nullify - add_foreign_key :statuses_tags, :statuses, on_delete: :cascade - add_foreign_key :statuses_tags, :tags, on_delete: :cascade - add_foreign_key :stream_entries, :accounts, on_delete: :cascade - add_foreign_key :subscriptions, :accounts, on_delete: :cascade - add_foreign_key :users, :accounts, on_delete: :cascade - add_foreign_key :web_settings, :users, on_delete: :cascade - add_foreign_key :oauth_access_grants, :users, column: :resource_owner_id, on_delete: :cascade - add_foreign_key :oauth_access_grants, :oauth_applications, column: :application_id, on_delete: :cascade - add_foreign_key :oauth_access_tokens, :users, column: :resource_owner_id, on_delete: :cascade - add_foreign_key :oauth_access_tokens, :oauth_applications, column: :application_id, on_delete: :cascade - end -end diff --git a/db/migrate/20180514075904_create_ico_tokens.rb b/db/migrate/20180514075904_create_ico_tokens.rb new file mode 100644 index 00000000000000..33923b8b384ce4 --- /dev/null +++ b/db/migrate/20180514075904_create_ico_tokens.rb @@ -0,0 +1,10 @@ +class CreateIcoTokens < ActiveRecord::Migration[5.1] + def change + create_table :ico_tokens do |t| + t.string :name + t.string :url + + t.timestamps + end + end +end diff --git a/db/migrate/20180514080029_create_ico_events.rb b/db/migrate/20180514080029_create_ico_events.rb new file mode 100644 index 00000000000000..fbbce621e5cee2 --- /dev/null +++ b/db/migrate/20180514080029_create_ico_events.rb @@ -0,0 +1,13 @@ +class CreateIcoEvents < ActiveRecord::Migration[5.1] + def change + create_table :ico_events do |t| + t.integer :ico_token_id + t.datetime :begin_at + t.datetime :end_at + t.float :sale_limit + t.string :name + + t.timestamps + end + end +end diff --git a/db/migrate/20180514080302_create_ico_requests.rb b/db/migrate/20180514080302_create_ico_requests.rb new file mode 100644 index 00000000000000..564dd8ce13fe0e --- /dev/null +++ b/db/migrate/20180514080302_create_ico_requests.rb @@ -0,0 +1,14 @@ +class CreateIcoRequests < ActiveRecord::Migration[5.1] + def change + create_table :ico_requests do |t| + t.integer :user_id + t.integer :ico_event_id + t.float :amount + t.string :email + t.string :eth_wallet_address + t.string :token_wallet_address + + t.timestamps + end + end +end diff --git a/db/migrate/20180514140000_revert_index_change_on_statuses_for_api_v1_accounts_account_id_statuses.rb b/db/migrate/20180514140000_revert_index_change_on_statuses_for_api_v1_accounts_account_id_statuses.rb index 4a8761fec3d212..2dba9cea0c6dc2 100644 --- a/db/migrate/20180514140000_revert_index_change_on_statuses_for_api_v1_accounts_account_id_statuses.rb +++ b/db/migrate/20180514140000_revert_index_change_on_statuses_for_api_v1_accounts_account_id_statuses.rb @@ -4,12 +4,12 @@ class RevertIndexChangeOnStatusesForApiV1AccountsAccountIdStatuses < ActiveRecor disable_ddl_transaction! def change - safety_assured do - add_index :statuses, [:account_id, :id, :visibility, :updated_at], order: { id: :desc }, algorithm: :concurrently, name: :index_statuses_20180106 unless index_exists?(:statuses, name: "index_statuses_20180106") - end + # safety_assured do + # add_index :statuses, [:account_id, :id, :visibility, :updated_at], order: { id: :desc }, algorithm: :concurrently, name: :index_statuses_20180106 unless index_exists?(:statuses, name: "index_statuses_20180106") + # end # These index may not exists (see migration 20180514130000) - remove_index :statuses, column: [:account_id, :id, :visibility], where: 'visibility IN (0, 1, 2)', algorithm: :concurrently if index_exists?(:statuses, [:account_id, :id, :visibility], where: 'visibility IN (0, 1, 2)') - remove_index :statuses, column: [:account_id, :id], where: 'visibility = 3', algorithm: :concurrently if index_exists?(:statuses, ["account_id", "id"], where: "(visibility = 3)") + # remove_index :statuses, column: [:account_id, :id, :visibility], where: 'visibility IN (0, 1, 2)', algorithm: :concurrently if index_exists?(:statuses, [:account_id, :id, :visibility], where: 'visibility IN (0, 1, 2)') + # remove_index :statuses, column: [:account_id, :id], where: 'visibility = 3', algorithm: :concurrently if index_exists?(:statuses, ["account_id", "id"], where: "(visibility = 3)") end end diff --git a/db/migrate/20180717052800_add_campaign_name_to_ico_requests.rb b/db/migrate/20180717052800_add_campaign_name_to_ico_requests.rb new file mode 100644 index 00000000000000..2293ae6611aff0 --- /dev/null +++ b/db/migrate/20180717052800_add_campaign_name_to_ico_requests.rb @@ -0,0 +1,5 @@ +class AddCampaignNameToIcoRequests < ActiveRecord::Migration[5.1] + def change + add_column :ico_requests, :campaign_name, :string, limit: 100 + end +end diff --git a/db/migrate/20180717073631_add_language_to_ico_requests.rb b/db/migrate/20180717073631_add_language_to_ico_requests.rb new file mode 100644 index 00000000000000..d4e77b1783da45 --- /dev/null +++ b/db/migrate/20180717073631_add_language_to_ico_requests.rb @@ -0,0 +1,5 @@ +class AddLanguageToIcoRequests < ActiveRecord::Migration[5.1] + def change + add_column :ico_requests, :language, :string, limit: 10 + end +end diff --git a/db/schema.rb b/db/schema.rb index 02032c54826b47..a51635c803b29c 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: 2018_07_07_154237) do +ActiveRecord::Schema.define(version: 20180717073631) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -201,6 +201,36 @@ t.index ["account_id", "target_account_id"], name: "index_follows_on_account_id_and_target_account_id", unique: true end + create_table "ico_events", force: :cascade do |t| + t.integer "ico_token_id" + t.datetime "begin_at" + t.datetime "end_at" + t.float "sale_limit" + t.string "name" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + create_table "ico_requests", force: :cascade do |t| + t.integer "user_id" + t.integer "ico_event_id" + t.float "amount" + t.string "email" + t.string "eth_wallet_address" + t.string "token_wallet_address" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "campaign_name", limit: 100 + t.string "language", limit: 10 + end + + create_table "ico_tokens", force: :cascade do |t| + t.string "name" + t.string "url" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "identities", id: :serial, force: :cascade do |t| t.integer "user_id" t.string "provider", default: "", null: false @@ -458,6 +488,7 @@ t.bigint "account_id", null: false t.bigint "application_id" t.bigint "in_reply_to_account_id" + t.json "enquete" t.index ["account_id", "id", "visibility", "updated_at"], name: "index_statuses_20180106", order: { id: :desc } t.index ["in_reply_to_id"], name: "index_statuses_on_in_reply_to_id" t.index ["reblog_of_id", "account_id"], name: "index_statuses_on_reblog_of_id_and_account_id" @@ -529,6 +560,8 @@ t.boolean "otp_required_for_login", default: false, null: false t.datetime "last_emailed_at" t.string "otp_backup_codes", array: true + t.string "provider" + t.string "uid" t.string "filtered_languages", default: [], null: false, array: true t.bigint "account_id", null: false t.boolean "disabled", default: false, null: false diff --git a/public/photon/logo.png b/public/photon/logo.png new file mode 100755 index 00000000000000..8d6dda83d2c6ff Binary files /dev/null and b/public/photon/logo.png differ diff --git a/spec/controllers/ico_requests_controller_spec.rb b/spec/controllers/ico_requests_controller_spec.rb new file mode 100644 index 00000000000000..9cf815dc28301f --- /dev/null +++ b/spec/controllers/ico_requests_controller_spec.rb @@ -0,0 +1,141 @@ +require 'rails_helper' + +# This spec was generated by rspec-rails when you ran the scaffold generator. +# It demonstrates how one might use RSpec to specify the controller code that +# was generated by Rails when you ran the scaffold generator. +# +# It assumes that the implementation code is generated by the rails scaffold +# generator. If you are using any extension libraries to generate different +# controller code, this generated spec may or may not pass. +# +# It only uses APIs available in rails and/or rspec-rails. There are a number +# of tools you can use to make these specs even more expressive, but we're +# sticking to rails and rspec-rails APIs to keep things simple and stable. +# +# Compared to earlier versions of this generator, there is very limited use of +# stubs and message expectations in this spec. Stubs are only used when there +# is no simpler way to get a handle on the object needed for the example. +# Message expectations are only used when there is no simpler way to specify +# that an instance is receiving a specific message. +# +# Also compared to earlier versions of this generator, there are no longer any +# expectations of assigns and templates rendered. These features have been +# removed from Rails core in Rails 5, but can be added back in via the +# `rails-controller-testing` gem. + +RSpec.describe IcoRequestsController, type: :controller do + + # This should return the minimal set of attributes required to create a valid + # IcoRequest. As you add validations to IcoRequest, be sure to + # adjust the attributes here as well. + let(:valid_attributes) { + skip("Add a hash of attributes valid for your model") + } + + let(:invalid_attributes) { + skip("Add a hash of attributes invalid for your model") + } + + # This should return the minimal set of values that should be in the session + # in order to pass any filters (e.g. authentication) defined in + # IcoRequestsController. Be sure to keep this updated too. + let(:valid_session) { {} } + + describe "GET #index" do + it "returns a success response" do + ico_request = IcoRequest.create! valid_attributes + get :index, params: {}, session: valid_session + expect(response).to be_success + end + end + + describe "GET #show" do + it "returns a success response" do + ico_request = IcoRequest.create! valid_attributes + get :show, params: {id: ico_request.to_param}, session: valid_session + expect(response).to be_success + end + end + + describe "GET #new" do + it "returns a success response" do + get :new, params: {}, session: valid_session + expect(response).to be_success + end + end + + describe "GET #edit" do + it "returns a success response" do + ico_request = IcoRequest.create! valid_attributes + get :edit, params: {id: ico_request.to_param}, session: valid_session + expect(response).to be_success + end + end + + describe "POST #create" do + context "with valid params" do + it "creates a new IcoRequest" do + expect { + post :create, params: {ico_request: valid_attributes}, session: valid_session + }.to change(IcoRequest, :count).by(1) + end + + it "redirects to the created ico_request" do + post :create, params: {ico_request: valid_attributes}, session: valid_session + expect(response).to redirect_to(IcoRequest.last) + end + end + + context "with invalid params" do + it "returns a success response (i.e. to display the 'new' template)" do + post :create, params: {ico_request: invalid_attributes}, session: valid_session + expect(response).to be_success + end + end + end + + describe "PUT #update" do + context "with valid params" do + let(:new_attributes) { + skip("Add a hash of attributes valid for your model") + } + + it "updates the requested ico_request" do + ico_request = IcoRequest.create! valid_attributes + put :update, params: {id: ico_request.to_param, ico_request: new_attributes}, session: valid_session + ico_request.reload + skip("Add assertions for updated state") + end + + it "redirects to the ico_request" do + ico_request = IcoRequest.create! valid_attributes + put :update, params: {id: ico_request.to_param, ico_request: valid_attributes}, session: valid_session + expect(response).to redirect_to(ico_request) + end + end + + context "with invalid params" do + it "returns a success response (i.e. to display the 'edit' template)" do + ico_request = IcoRequest.create! valid_attributes + put :update, params: {id: ico_request.to_param, ico_request: invalid_attributes}, session: valid_session + expect(response).to be_success + end + end + end + + describe "DELETE #destroy" do + it "destroys the requested ico_request" do + ico_request = IcoRequest.create! valid_attributes + expect { + delete :destroy, params: {id: ico_request.to_param}, session: valid_session + }.to change(IcoRequest, :count).by(-1) + end + + it "redirects to the ico_requests list" do + ico_request = IcoRequest.create! valid_attributes + delete :destroy, params: {id: ico_request.to_param}, session: valid_session + expect(response).to redirect_to(ico_requests_url) + end + end + +end diff --git a/spec/fabricators/ico_event_fabricator.rb b/spec/fabricators/ico_event_fabricator.rb new file mode 100644 index 00000000000000..9197518a4d5980 --- /dev/null +++ b/spec/fabricators/ico_event_fabricator.rb @@ -0,0 +1,6 @@ +Fabricator(:ico_event) do + ico_token_id 1 + begin_at "2018-05-14 17:00:29" + end_at "2018-05-14 17:00:29" + name "MyString" +end diff --git a/spec/fabricators/ico_request_fabricator.rb b/spec/fabricators/ico_request_fabricator.rb new file mode 100644 index 00000000000000..6fc89eade14b8e --- /dev/null +++ b/spec/fabricators/ico_request_fabricator.rb @@ -0,0 +1,8 @@ +Fabricator(:ico_request) do + user_id 1 + ico_event_id 1 + amount 1.5 + email "MyString" + eth_wallet_address "MyString" + token_wallet_address "MyString" +end diff --git a/spec/fabricators/ico_token_fabricator.rb b/spec/fabricators/ico_token_fabricator.rb new file mode 100644 index 00000000000000..748b1afde30ef2 --- /dev/null +++ b/spec/fabricators/ico_token_fabricator.rb @@ -0,0 +1,4 @@ +Fabricator(:ico_token) do + name "MyString" + url "MyString" +end diff --git a/spec/helpers/ico_requests_helper_spec.rb b/spec/helpers/ico_requests_helper_spec.rb new file mode 100644 index 00000000000000..df2d57145271cd --- /dev/null +++ b/spec/helpers/ico_requests_helper_spec.rb @@ -0,0 +1,15 @@ +require 'rails_helper' + +# Specs in this file have access to a helper object that includes +# the IcoRequestsHelper. For example: +# +# describe IcoRequestsHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# expect(helper.concat_strings("this","that")).to eq("this that") +# end +# end +# end +RSpec.describe IcoRequestsHelper, type: :helper do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/models/ico_event_spec.rb b/spec/models/ico_event_spec.rb new file mode 100644 index 00000000000000..ee1b039161c46a --- /dev/null +++ b/spec/models/ico_event_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe IcoEvent, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/models/ico_request_spec.rb b/spec/models/ico_request_spec.rb new file mode 100644 index 00000000000000..953ddc68e5c031 --- /dev/null +++ b/spec/models/ico_request_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe IcoRequest, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/models/ico_token_spec.rb b/spec/models/ico_token_spec.rb new file mode 100644 index 00000000000000..bbe7af801f01c9 --- /dev/null +++ b/spec/models/ico_token_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe IcoToken, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/requests/ico_requests_spec.rb b/spec/requests/ico_requests_spec.rb new file mode 100644 index 00000000000000..4ab5617d4ea159 --- /dev/null +++ b/spec/requests/ico_requests_spec.rb @@ -0,0 +1,10 @@ +require 'rails_helper' + +RSpec.describe "IcoRequests", type: :request do + describe "GET /ico_requests" do + it "works! (now write some real specs)" do + get ico_requests_path + expect(response).to have_http_status(200) + end + end +end diff --git a/spec/routing/ico_requests_routing_spec.rb b/spec/routing/ico_requests_routing_spec.rb new file mode 100644 index 00000000000000..7be169c61576ad --- /dev/null +++ b/spec/routing/ico_requests_routing_spec.rb @@ -0,0 +1,39 @@ +require "rails_helper" + +RSpec.describe IcoRequestsController, type: :routing do + describe "routing" do + + it "routes to #index" do + expect(:get => "/ico_requests").to route_to("ico_requests#index") + end + + it "routes to #new" do + expect(:get => "/ico_requests/new").to route_to("ico_requests#new") + end + + it "routes to #show" do + expect(:get => "/ico_requests/1").to route_to("ico_requests#show", :id => "1") + end + + it "routes to #edit" do + expect(:get => "/ico_requests/1/edit").to route_to("ico_requests#edit", :id => "1") + end + + it "routes to #create" do + expect(:post => "/ico_requests").to route_to("ico_requests#create") + end + + it "routes to #update via PUT" do + expect(:put => "/ico_requests/1").to route_to("ico_requests#update", :id => "1") + end + + it "routes to #update via PATCH" do + expect(:patch => "/ico_requests/1").to route_to("ico_requests#update", :id => "1") + end + + it "routes to #destroy" do + expect(:delete => "/ico_requests/1").to route_to("ico_requests#destroy", :id => "1") + end + + end +end diff --git a/spec/views/about/show.html.haml_spec.rb b/spec/views/about/show.html.haml_spec.rb index cbe5aa93b68923..540cab4509c52b 100644 --- a/spec/views/about/show.html.haml_spec.rb +++ b/spec/views/about/show.html.haml_spec.rb @@ -13,7 +13,7 @@ site_title: 'something', site_description: 'something', version_number: '1.0', - source_url: 'https://github.com/tootsuite/mastodon', + source_url: 'https://github.com/kibousoft/mastodon', open_registrations: false, thumbnail: nil, hero: nil, diff --git a/spec/views/ico_requests/edit.html.haml_spec.rb b/spec/views/ico_requests/edit.html.haml_spec.rb new file mode 100644 index 00000000000000..ea770bff634c86 --- /dev/null +++ b/spec/views/ico_requests/edit.html.haml_spec.rb @@ -0,0 +1,27 @@ +require 'rails_helper' + +RSpec.describe "ico_requests/edit", type: :view do + before(:each) do + @ico_request = assign(:ico_request, IcoRequest.create!( + :amount => 1.5, + :email => "MyString", + :eth_wallet_address => "MyString", + :token_wallet_address => "MyString" + )) + end + + it "renders the edit ico_request form" do + render + + assert_select "form[action=?][method=?]", ico_request_path(@ico_request), "post" do + + assert_select "input[name=?]", "ico_request[amount]" + + assert_select "input[name=?]", "ico_request[email]" + + assert_select "input[name=?]", "ico_request[eth_wallet_address]" + + assert_select "input[name=?]", "ico_request[token_wallet_address]" + end + end +end diff --git a/spec/views/ico_requests/index.html.haml_spec.rb b/spec/views/ico_requests/index.html.haml_spec.rb new file mode 100644 index 00000000000000..0b4faefd218eaa --- /dev/null +++ b/spec/views/ico_requests/index.html.haml_spec.rb @@ -0,0 +1,28 @@ +require 'rails_helper' + +RSpec.describe "ico_requests/index", type: :view do + before(:each) do + assign(:ico_requests, [ + IcoRequest.create!( + :amount => 2.5, + :email => "Email", + :eth_wallet_address => "Eth Wallet Address", + :token_wallet_address => "Token Wallet Address" + ), + IcoRequest.create!( + :amount => 2.5, + :email => "Email", + :eth_wallet_address => "Eth Wallet Address", + :token_wallet_address => "Token Wallet Address" + ) + ]) + end + + it "renders a list of ico_requests" do + render + assert_select "tr>td", :text => 2.5.to_s, :count => 2 + assert_select "tr>td", :text => "Email".to_s, :count => 2 + assert_select "tr>td", :text => "Eth Wallet Address".to_s, :count => 2 + assert_select "tr>td", :text => "Token Wallet Address".to_s, :count => 2 + end +end diff --git a/spec/views/ico_requests/new.html.haml_spec.rb b/spec/views/ico_requests/new.html.haml_spec.rb new file mode 100644 index 00000000000000..01de4e70bb47b8 --- /dev/null +++ b/spec/views/ico_requests/new.html.haml_spec.rb @@ -0,0 +1,27 @@ +require 'rails_helper' + +RSpec.describe "ico_requests/new", type: :view do + before(:each) do + assign(:ico_request, IcoRequest.new( + :amount => 1.5, + :email => "MyString", + :eth_wallet_address => "MyString", + :token_wallet_address => "MyString" + )) + end + + it "renders new ico_request form" do + render + + assert_select "form[action=?][method=?]", ico_requests_path, "post" do + + assert_select "input[name=?]", "ico_request[amount]" + + assert_select "input[name=?]", "ico_request[email]" + + assert_select "input[name=?]", "ico_request[eth_wallet_address]" + + assert_select "input[name=?]", "ico_request[token_wallet_address]" + end + end +end diff --git a/spec/views/ico_requests/show.html.haml_spec.rb b/spec/views/ico_requests/show.html.haml_spec.rb new file mode 100644 index 00000000000000..b8618b6a22b5e0 --- /dev/null +++ b/spec/views/ico_requests/show.html.haml_spec.rb @@ -0,0 +1,20 @@ +require 'rails_helper' + +RSpec.describe "ico_requests/show", type: :view do + before(:each) do + @ico_request = assign(:ico_request, IcoRequest.create!( + :amount => 2.5, + :email => "Email", + :eth_wallet_address => "Eth Wallet Address", + :token_wallet_address => "Token Wallet Address" + )) + end + + it "renders attributes in

" do + render + expect(rendered).to match(/2.5/) + expect(rendered).to match(/Email/) + expect(rendered).to match(/Eth Wallet Address/) + expect(rendered).to match(/Token Wallet Address/) + end +end diff --git a/streaming/daemon.js b/streaming/daemon.js new file mode 100644 index 00000000000000..2a34d402ab76fc --- /dev/null +++ b/streaming/daemon.js @@ -0,0 +1,2 @@ +require('babel-register'); +require('./index.js');