├── .devcontainer
├── Dockerfile
├── devcontainer.json
└── docker-compose.yml
├── .dockerignore
├── .github
├── dependabot.yml
└── workflows
│ ├── ci.yml
│ └── known_hosts
├── .gitignore
├── .gitmodules
├── Dockerfile
├── Dockerfile.production
├── Gemfile
├── Gemfile.lock
├── LICENSE
├── README.rdoc
├── Rakefile
├── Steepfile
├── app
├── assets
│ ├── config
│ │ └── manifest.js
│ ├── images
│ │ └── .keep
│ ├── javascripts
│ │ └── application.js
│ └── stylesheets
│ │ ├── _articles.scss
│ │ ├── _base.scss
│ │ ├── admin
│ │ └── articles.scss
│ │ └── application.scss
├── avo
│ └── resources
│ │ └── article_resource.rb
├── controllers
│ ├── application_controller.rb
│ ├── articles_controller.rb
│ ├── avo
│ │ └── articles_controller.rb
│ ├── concerns
│ │ └── .keep
│ ├── graphql_controller.rb
│ └── sessions_controller.rb
├── graphql
│ ├── mutations
│ │ └── .keep
│ ├── tdnm_schema.rb
│ └── types
│ │ ├── .keep
│ │ ├── article_type.rb
│ │ ├── base_enum.rb
│ │ ├── base_input_object.rb
│ │ ├── base_interface.rb
│ │ ├── base_object.rb
│ │ ├── base_scalar.rb
│ │ ├── base_union.rb
│ │ ├── mutation_type.rb
│ │ └── query_type.rb
├── helpers
│ ├── application_helper.rb
│ └── articles_helper.rb
├── jobs
│ └── application_job.rb
├── mailers
│ └── .keep
├── models
│ ├── .keep
│ ├── application_record.rb
│ ├── article.rb
│ ├── concerns
│ │ └── .keep
│ └── weblog.rb
└── views
│ ├── articles
│ ├── index.atom.builder
│ ├── index.html.slim
│ └── show.html.slim
│ ├── kaminari
│ ├── _first_page.html.slim
│ ├── _gap.html.slim
│ ├── _last_page.html.slim
│ ├── _next_page.html.slim
│ ├── _page.html.slim
│ ├── _paginator.html.slim
│ └── _prev_page.html.slim
│ ├── layouts
│ └── application.html.slim
│ └── sessions
│ └── new.html.slim
├── bin
├── bundle
├── rails
├── rake
├── render-build.sh
├── setup
├── start
├── steep
└── yarn
├── config.ru
├── config
├── application.rb
├── boot.rb
├── cable.yml
├── credentials.yml.enc
├── database.yml
├── environment.rb
├── environments
│ ├── development.rb
│ ├── production.rb
│ └── test.rb
├── initializers
│ ├── application_controller_renderer.rb
│ ├── assets.rb
│ ├── avo.rb
│ ├── backtrace_silencers.rb
│ ├── content_security_policy.rb
│ ├── cookies_serializer.rb
│ ├── filter_parameter_logging.rb
│ ├── inflections.rb
│ ├── meta_tags.rb
│ ├── mime_types.rb
│ ├── omniauth.rb
│ ├── permissions_policy.rb
│ ├── session_store.rb
│ └── wrap_parameters.rb
├── locales
│ ├── avo.en.yml
│ └── en.yml
├── puma.rb
├── routes.rb
├── sitemap.rb
├── spring.rb
└── storage.yml
├── db
├── migrate
│ ├── 20150803141807_create_articles.rb
│ ├── 20150804044739_create_weblogs.rb
│ ├── 20160110151755_change_column_article_body_to_text.rb
│ ├── 20161023132949_add_draft_to_articles.rb
│ ├── 20180326163716_add_default_eye_catching_image_url_to_weblog.rb
│ ├── 20180416143233_rename_url_title_to_slug_on_articles.rb
│ ├── 20180416150121_add_eye_catching_image_url_to_articles.rb
│ ├── 20190604125626_change_articles_eyecatching_url_size.rb
│ ├── 20190924161405_add_foreign_key_constraint_to_active_storage_attachments_for_blob_id.active_storage.rb
│ ├── 20200324153331_add_index_to_articles_published_on.rb
│ ├── 20210908153117_add_unique_index_to_article_title.rb
│ └── 20230303004038_rename_column_eye_catching_image_url_to_featured_imaeg_url.rb
├── schema.rb
└── seeds.rb
├── docker-compose.yml
├── lib
├── assets
│ └── .keep
└── tasks
│ ├── .keep
│ ├── import.thor
│ └── rbs.rake
├── log
└── .keep
├── public
├── 404.html
├── 422.html
├── 500.html
├── favicon.ico
└── robots.txt
├── sig
└── rbs_rails
│ ├── app
│ └── models
│ │ ├── article.rbs
│ │ └── weblog.rbs
│ ├── model_dependencies.rbs
│ └── path_helpers.rbs
├── test
├── application_system_test_case.rb
├── controllers
│ ├── .keep
│ └── articles_controller_test.rb
├── fixtures
│ ├── .keep
│ ├── articles.yml
│ └── weblogs.yml
├── helpers
│ └── .keep
├── integration
│ └── .keep
├── mailers
│ └── .keep
├── models
│ ├── .keep
│ ├── article_test.rb
│ └── weblog_test.rb
├── system
│ └── articles_test.rb
└── test_helper.rb
└── tmp
└── .keep
/.devcontainer/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM rubylang/ruby:2.7.0-bionic
2 |
3 | RUN apt-get update -q && apt-get install -y --no-install-recommends -q \
4 | curl \
5 | g++ \
6 | gnupg \
7 | libmysqlclient-dev \
8 | mysql-client \
9 | openssh-client \
10 | && apt-get clean && rm -rf /var/lib/apt/lists/*
11 |
12 | RUN curl -sL https://deb.nodesource.com/setup_12.x | bash - \
13 | && apt-get update -q && apt-get install -y --no-install-recommends -q nodejs \
14 | && apt-get clean && rm -rf /var/lib/apt/lists/*
15 |
16 | RUN bundle config jobs 3
17 | RUN bundle config path ./vendor/bundle
18 |
--------------------------------------------------------------------------------
/.devcontainer/devcontainer.json:
--------------------------------------------------------------------------------
1 | // For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at:
2 | // https://github.com/microsoft/vscode-dev-containers/tree/v0.101.1/containers/docker-existing-docker-compose
3 | // If you want to run as a non-root user in the container, see .devcontainer/docker-compose.yml.
4 | {
5 | "name": "Existing Docker Compose (Extend)",
6 |
7 | // Update the 'dockerComposeFile' list if you have more compose files or use different names.
8 | // The .devcontainer/docker-compose.yml file contains any overrides you need/want to make.
9 | "dockerComposeFile": [
10 | "../docker-compose.yml",
11 | "docker-compose.yml"
12 | ],
13 |
14 | // The 'service' property is the name of the service for the container that VS Code should
15 | // use. Update this value and .devcontainer/docker-compose.yml to the real service name.
16 | "service": "app",
17 |
18 | // The optional 'workspaceFolder' property is the path VS Code should open by default when
19 | // connected. This is typically a file mount in .devcontainer/docker-compose.yml
20 | "workspaceFolder": "/workspace",
21 |
22 | // Set *default* container specific settings.json values on container create.
23 | "settings": {
24 | "terminal.integrated.shell.linux": null
25 | },
26 |
27 | // Add the IDs of extensions you want installed when the container is created.
28 | "extensions": []
29 |
30 | // Uncomment the next line if you want start specific services in your Docker Compose config.
31 | // "runServices": [],
32 |
33 | // Uncomment the next line if you want to keep your containers running after VS Code shuts down.
34 | // "shutdownAction": "none",
35 |
36 | // Uncomment the next line to run commands after the container is created - for example installing git.
37 | // "postCreateCommand": "apt-get update && apt-get install -y git",
38 |
39 | // Uncomment to connect as a non-root user. See https://aka.ms/vscode-remote/containers/non-root.
40 | // "remoteUser": "vscode"
41 | }
42 |
--------------------------------------------------------------------------------
/.devcontainer/docker-compose.yml:
--------------------------------------------------------------------------------
1 | #-------------------------------------------------------------------------------------------------------------
2 | # Copyright (c) Microsoft Corporation. All rights reserved.
3 | # Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
4 | #-------------------------------------------------------------------------------------------------------------
5 |
6 | version: '3'
7 | services:
8 | # Update this to the name of the service you want to work with in your docker-compose.yml file
9 | app:
10 | # You may want to add a non-root user to your Dockerfile and uncomment the line below
11 | # to cause all processes to run as this user. Once present, you can also simply
12 | # use the "remoteUser" property in devcontainer.json if you just want VS Code and
13 | # its sub-processes (terminals, tasks, debugging) to execute as the user. On Linux,
14 | # you may need to ensure the UID and GID of the container user you create matches your
15 | # local user. See https://aka.ms/vscode-remote/containers/non-root for details.
16 | # user: vscode
17 |
18 | # Uncomment if you want to add a different Dockerfile in the .devcontainer folder
19 | build:
20 | context: .devcontainer
21 | dockerfile: Dockerfile
22 |
23 | # Uncomment if you want to expose any additional ports. The snippet below exposes port 3000.
24 | # ports:
25 | # - 3000:3000
26 |
27 | volumes:
28 | # Update this to wherever you want VS Code to mount the folder of your project
29 | - .:/workspace:cached
30 | - bundle_cache:/workspace/vendor/bundle
31 |
32 | # Uncomment the next line to use Docker from inside the container. See https://aka.ms/vscode-remote/samples/docker-in-docker-compose for details.
33 | # - /var/run/docker.sock:/var/run/docker.sock
34 |
35 | # Uncomment the next four lines if you will use a ptrace-based debugger like C++, Go, and Rust.
36 | # cap_add:
37 | # - SYS_PTRACE
38 | # security_opt:
39 | # - seccomp:unconfined
40 |
41 | # Overrides default command so things don't shut down after the process ends.
42 | command: /bin/sh -c "while sleep 1000; do :; done"
43 |
44 | volumes:
45 | bundle_cache:
46 |
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | .dockerignore
2 |
3 | .bundle
4 | .ruby-version
5 |
6 | .git
7 | .gitignore
8 |
9 | .circleci
10 |
11 | config/master.key
12 |
13 | log
14 | node_modules
15 | tmp
16 | vendor
17 |
18 | tdnm.env
19 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: bundler
4 | directory: "/"
5 | schedule:
6 | interval: daily
7 | time: "20:00"
8 | open-pull-requests-limit: 10
9 | assignees:
10 | - kenchan
11 | versioning-strategy: lockfile-only
12 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on: [push]
4 |
5 | env:
6 | RAILS_MASTER_KEY: ${{ secrets.RAILS_MASTER_KEY }}
7 |
8 | jobs:
9 | test:
10 | runs-on: ubuntu-latest
11 | services:
12 | postgres:
13 | image: postgres:14
14 | env:
15 | POSTGRES_PASSWORD: postgres
16 | options: --health-cmd=pg_isready --health-interval=10s --health-timeout=5s --health-retries=3
17 | ports:
18 | - 5432:5432
19 |
20 | steps:
21 | - uses: actions/checkout@v2
22 |
23 | - name: Setup Ruby
24 | uses: ruby/setup-ruby@v1
25 | with:
26 | ruby-version: 3.1
27 | bundler-cache: true
28 |
29 | - name: Setup database
30 | run: bin/rails db:prepare
31 | env:
32 | DATABASE_PORT: 5432
33 | DATABASE_PASSWORD: postgres
34 |
35 | - name: Run tests
36 | run: bin/rails test
37 | env:
38 | DATABASE_PORT: 5432
39 | DATABASE_PASSWORD: postgres
40 |
41 | - name: Run system tests
42 | run: bin/rails test:system
43 | env:
44 | DATABASE_PORT: 5432
45 | DATABASE_PASSWORD: postgres
46 |
--------------------------------------------------------------------------------
/.github/workflows/known_hosts:
--------------------------------------------------------------------------------
1 | |1|dNqLqa9OAvZdkit8qPBEySDXKxQ=|pWoNJhTUgrRvkNfxaIMMJNcDi7U= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCrbTJsCPOdmAel+2/gW0ziUsOveWyOjfWm7f4UX1TcVpPI1zqDPcReTZybYwLvdIaIzK9GgmUZ3Y8n2Pi9YD90Am13xNMHULsg/mt90r9THfC35m8rxnzUJ/DXX0T3QQD9ve69DOCsRe3YRgdQOHUeK4LwVSFYTwVN0fmkIl4a3MweFiu9r42OGtPE9r2Kq4kmBcgLFzbO006eCs2Q2V2kj9AEt3zvIPkV8NJKAJxUEBIEadxIkgULCxDAdwa7UXJjNFGb7xFg+n+lXRMHfH3OhakbHjroTCkuxnBKwcJqGSIvlUZ9Ztw4qGHkUcfZc6HDqFRfNZLb3jnkFImZHKzZ
2 | |1|dseivxwEnXaRQWLWbLT/EC7Iiqw=|AczEhQS6lhdxKAaYQNahUiTKDbU= ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBsyEaY2RqedDxTP3bvdpdIG9hm9Kgr97apkI7RTrm2r
3 | |1|Y09qAY+b1wpHMue6gY9SIvyBvL4=|MozEgll+LusLMI6xAnQCCiRIwYE= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBC4pfoNkPrtuW1qHg0wFetlh1/Dhpz2cwgCfMlUBpFSpn8ZUTo97/thZdmu5HFBGpYEZ3pOh8M6VTo+PD2MkAWw=
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files for more about ignoring files.
2 | #
3 | # If you find yourself ignoring temporary files generated by your text editor
4 | # or operating system, you probably want to add a global ignore instead:
5 | # git config --global core.excludesfile '~/.gitignore_global'
6 |
7 | # Ignore bundler config.
8 | /.bundle
9 |
10 | # Ignore the default SQLite database.
11 | /db/*.sqlite3
12 | /db/*.sqlite3-journal
13 |
14 | # Ignore all logfiles and tempfiles.
15 | /log/*
16 | /tmp/*
17 | !/log/.keep
18 | !/tmp/.keep
19 |
20 | /node_modules
21 | /yarn-error.log
22 |
23 | .byebug_history
24 |
25 | # Ignore master key for decrypting credentials and more.
26 | /config/master.key
27 |
28 | tdnm.env
29 |
30 | /vendor/*
31 | !/vendor/rbs
32 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "vendor/rbs/gem_rbs_collection"]
2 | path = vendor/rbs/gem_rbs_collection
3 | url = https://github.com/ruby/gem_rbs_collection.git
4 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM rubylang/ruby:3.1-dev-jammy
2 |
3 | RUN apt-get update -q && apt-get install -y --no-install-recommends -q \
4 | g++ \
5 | postgresql-client \
6 | libpq-dev \
7 | wait-for-it \
8 | automake \
9 | libtool \
10 | libyaml-dev \
11 | && apt-get clean && rm -rf /var/lib/apt/lists/*
12 |
13 | RUN curl -sL https://deb.nodesource.com/setup_16.x | bash - \
14 | && apt-get update -q && apt-get install -y --no-install-recommends -q nodejs \
15 | && apt-get clean && rm -rf /var/lib/apt/lists/*
16 |
17 | EXPOSE 3000
18 | WORKDIR /app
19 |
20 | RUN bundle config set path /app/vendor/bundle
21 |
--------------------------------------------------------------------------------
/Dockerfile.production:
--------------------------------------------------------------------------------
1 | FROM rubylang/ruby:3.1
2 |
3 | ENV RAILS_ENV production
4 | ENV RAILS_SERVE_STATIC_FILES true
5 | ENV RAILS_LOG_TO_STDOUT true
6 |
7 | WORKDIR /app
8 |
9 | RUN apt-get update -q && apt-get install -y --no-install-recommends -q \
10 | g++ \
11 | postgresql-client \
12 | libpq-dev \
13 | automake \
14 | libtool \
15 | && apt-get clean && rm -rf /var/lib/apt/lists/*
16 |
17 | RUN curl -sL https://deb.nodesource.com/setup_16.x | bash - \
18 | && apt-get update -q && apt-get install -y --no-install-recommends -q nodejs \
19 | && apt-get clean && rm -rf /var/lib/apt/lists/*
20 |
21 | RUN bundle config set deploytment true
22 |
23 | COPY Gemfile* /app
24 | RUN bundle install
25 |
26 | COPY . /app
27 |
28 | CMD ["bin/start"]
29 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | git_source(:github) do |repo_name|
4 | repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
5 | "https://github.com/#{repo_name}.git"
6 | end
7 |
8 | gem 'rails', '~> 7.0.0'
9 |
10 | gem 'commonmarker'
11 | gem 'graphql'
12 | gem 'jbuilder'
13 | gem 'kaminari'
14 | gem 'marked-rails'
15 | gem 'meta-tags'
16 | gem 'pg'
17 | gem 'puma'
18 | gem 'sass-rails'
19 | gem 'sdoc', '~> 1.0.0', group: :doc
20 | gem 'sitemap_generator'
21 | gem 'slim-rails'
22 | gem 'uglifier'
23 | gem 'turbo-rails', '~> 1.0.0'
24 | gem 'avo'
25 | gem 'omniauth-siwe', github: 'spruceid/omniauth-siwe', branch: 'main'
26 | gem "omniauth-rails_csrf_protection"
27 |
28 | group :production do
29 | gem 'lograge'
30 | gem 'rails_12factor'
31 | gem 'stackdriver'
32 | end
33 |
34 | group :development do
35 | gem 'graphiql-rails'
36 | gem 'rbs_rails', require: false
37 | end
38 |
39 | group :development, :test do
40 | gem 'byebug'
41 | gem 'capybara'
42 | gem 'listen'
43 | gem 'pry-rails'
44 | gem 'selenium-webdriver'
45 | end
46 |
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GIT
2 | remote: https://github.com/spruceid/omniauth-siwe.git
3 | revision: 1c08b02d25c5eac86e1a8b00bcc6af05fc7e1858
4 | branch: main
5 | specs:
6 | omniauth-siwe (0.1.0)
7 | bcrypt
8 | omniauth
9 | omniauth_openid_connect
10 | siwe
11 |
12 | GEM
13 | remote: https://rubygems.org/
14 | specs:
15 | actioncable (7.0.8)
16 | actionpack (= 7.0.8)
17 | activesupport (= 7.0.8)
18 | nio4r (~> 2.0)
19 | websocket-driver (>= 0.6.1)
20 | actionmailbox (7.0.8)
21 | actionpack (= 7.0.8)
22 | activejob (= 7.0.8)
23 | activerecord (= 7.0.8)
24 | activestorage (= 7.0.8)
25 | activesupport (= 7.0.8)
26 | mail (>= 2.7.1)
27 | net-imap
28 | net-pop
29 | net-smtp
30 | actionmailer (7.0.8)
31 | actionpack (= 7.0.8)
32 | actionview (= 7.0.8)
33 | activejob (= 7.0.8)
34 | activesupport (= 7.0.8)
35 | mail (~> 2.5, >= 2.5.4)
36 | net-imap
37 | net-pop
38 | net-smtp
39 | rails-dom-testing (~> 2.0)
40 | actionpack (7.0.8)
41 | actionview (= 7.0.8)
42 | activesupport (= 7.0.8)
43 | rack (~> 2.0, >= 2.2.4)
44 | rack-test (>= 0.6.3)
45 | rails-dom-testing (~> 2.0)
46 | rails-html-sanitizer (~> 1.0, >= 1.2.0)
47 | actiontext (7.0.8)
48 | actionpack (= 7.0.8)
49 | activerecord (= 7.0.8)
50 | activestorage (= 7.0.8)
51 | activesupport (= 7.0.8)
52 | globalid (>= 0.6.0)
53 | nokogiri (>= 1.8.5)
54 | actionview (7.0.8)
55 | activesupport (= 7.0.8)
56 | builder (~> 3.1)
57 | erubi (~> 1.4)
58 | rails-dom-testing (~> 2.0)
59 | rails-html-sanitizer (~> 1.1, >= 1.2.0)
60 | active_link_to (1.0.5)
61 | actionpack
62 | addressable
63 | activejob (7.0.8)
64 | activesupport (= 7.0.8)
65 | globalid (>= 0.3.6)
66 | activemodel (7.0.8)
67 | activesupport (= 7.0.8)
68 | activerecord (7.0.8)
69 | activemodel (= 7.0.8)
70 | activesupport (= 7.0.8)
71 | activestorage (7.0.8)
72 | actionpack (= 7.0.8)
73 | activejob (= 7.0.8)
74 | activerecord (= 7.0.8)
75 | activesupport (= 7.0.8)
76 | marcel (~> 1.0)
77 | mini_mime (>= 1.1.0)
78 | activesupport (7.0.8)
79 | concurrent-ruby (~> 1.0, >= 1.0.2)
80 | i18n (>= 1.6, < 2)
81 | minitest (>= 5.1)
82 | tzinfo (~> 2.0)
83 | addressable (2.8.5)
84 | public_suffix (>= 2.0.2, < 6.0)
85 | aes_key_wrap (1.1.0)
86 | ast (2.4.2)
87 | attr_required (1.0.1)
88 | avo (2.43.0)
89 | actionview (>= 6.0)
90 | active_link_to
91 | activerecord (>= 6.0)
92 | addressable
93 | docile
94 | dry-initializer
95 | httparty
96 | inline_svg
97 | meta-tags
98 | pagy
99 | turbo-rails
100 | view_component (>= 2.54.0)
101 | zeitwerk (>= 2.6.2)
102 | bcrypt (3.1.18)
103 | bindata (2.4.15)
104 | builder (3.2.4)
105 | byebug (11.1.3)
106 | capybara (3.39.2)
107 | addressable
108 | matrix
109 | mini_mime (>= 0.1.3)
110 | nokogiri (~> 1.8)
111 | rack (>= 1.6.0)
112 | rack-test (>= 0.6.3)
113 | regexp_parser (>= 1.5, < 3.0)
114 | xpath (~> 3.2)
115 | coderay (1.1.3)
116 | commonmarker (1.0.4)
117 | rb_sys (~> 0.9)
118 | concurrent-ruby (1.2.2)
119 | crass (1.0.6)
120 | date (3.3.3)
121 | docile (1.4.0)
122 | dry-initializer (3.1.1)
123 | erubi (1.12.0)
124 | eth (0.5.10)
125 | keccak (~> 1.3)
126 | konstructor (~> 1.0)
127 | openssl (>= 2.2, < 4.0)
128 | rbsecp256k1 (~> 5.1)
129 | scrypt (~> 3.0)
130 | execjs (2.8.1)
131 | faraday (2.7.4)
132 | faraday-net_http (>= 2.0, < 3.1)
133 | ruby2_keywords (>= 0.0.4)
134 | faraday-follow_redirects (0.3.0)
135 | faraday (>= 1, < 3)
136 | faraday-net_http (3.0.2)
137 | faraday-retry (2.0.0)
138 | faraday (~> 2.0)
139 | ffi (1.15.5)
140 | ffi-compiler (1.0.1)
141 | ffi (>= 1.0.0)
142 | rake
143 | gapic-common (0.17.1)
144 | faraday (>= 1.9, < 3.a)
145 | faraday-retry (>= 1.0, < 3.a)
146 | google-protobuf (~> 3.14)
147 | googleapis-common-protos (>= 1.3.12, < 2.a)
148 | googleapis-common-protos-types (>= 1.3.1, < 2.a)
149 | googleauth (~> 1.0)
150 | grpc (~> 1.36)
151 | globalid (1.2.1)
152 | activesupport (>= 6.1)
153 | google-cloud-core (1.6.0)
154 | google-cloud-env (~> 1.0)
155 | google-cloud-errors (~> 1.0)
156 | google-cloud-env (1.6.0)
157 | faraday (>= 0.17.3, < 3.0)
158 | google-cloud-error_reporting (0.42.2)
159 | concurrent-ruby (~> 1.1)
160 | google-cloud-core (~> 1.5)
161 | google-cloud-error_reporting-v1beta1 (~> 0.0)
162 | stackdriver-core (~> 1.3)
163 | google-cloud-error_reporting-v1beta1 (0.5.1)
164 | gapic-common (>= 0.16.0, < 2.a)
165 | google-cloud-errors (~> 1.0)
166 | google-cloud-errors (1.3.0)
167 | google-cloud-logging (2.3.2)
168 | concurrent-ruby (~> 1.1)
169 | google-cloud-core (~> 1.5)
170 | google-cloud-logging-v2 (~> 0.0)
171 | stackdriver-core (~> 1.3)
172 | google-cloud-logging-v2 (0.8.1)
173 | gapic-common (>= 0.10, < 2.a)
174 | google-cloud-errors (~> 1.0)
175 | google-cloud-trace (0.42.1)
176 | concurrent-ruby (~> 1.1)
177 | google-cloud-core (~> 1.5)
178 | google-cloud-trace-v1 (~> 0.0)
179 | google-cloud-trace-v2 (~> 0.0)
180 | stackdriver-core (~> 1.3)
181 | google-cloud-trace-v1 (0.4.0)
182 | gapic-common (>= 0.10, < 2.a)
183 | google-cloud-errors (~> 1.0)
184 | google-cloud-trace-v2 (0.4.1)
185 | gapic-common (>= 0.16.0, < 2.a)
186 | google-cloud-errors (~> 1.0)
187 | google-protobuf (3.24.0)
188 | googleapis-common-protos (1.4.0)
189 | google-protobuf (~> 3.14)
190 | googleapis-common-protos-types (~> 1.2)
191 | grpc (~> 1.27)
192 | googleapis-common-protos-types (1.8.0)
193 | google-protobuf (~> 3.18)
194 | googleauth (1.3.0)
195 | faraday (>= 0.17.3, < 3.a)
196 | jwt (>= 1.4, < 3.0)
197 | memoist (~> 0.16)
198 | multi_json (~> 1.11)
199 | os (>= 0.9, < 2.0)
200 | signet (>= 0.16, < 2.a)
201 | graphiql-rails (1.9.0)
202 | railties
203 | sprockets-rails
204 | graphql (2.2.5)
205 | racc (~> 1.4)
206 | grpc (1.57.0)
207 | google-protobuf (~> 3.23)
208 | googleapis-common-protos-types (~> 1.0)
209 | hashie (5.0.0)
210 | httparty (0.21.0)
211 | mini_mime (>= 1.0.0)
212 | multi_xml (>= 0.5.2)
213 | httpclient (2.8.3)
214 | i18n (1.14.1)
215 | concurrent-ruby (~> 1.0)
216 | inline_svg (1.9.0)
217 | activesupport (>= 3.0)
218 | nokogiri (>= 1.6)
219 | jbuilder (2.11.5)
220 | actionview (>= 5.0.0)
221 | activesupport (>= 5.0.0)
222 | json-jwt (1.16.3)
223 | activesupport (>= 4.2)
224 | aes_key_wrap
225 | bindata
226 | faraday (~> 2.0)
227 | faraday-follow_redirects
228 | jwt (2.7.0)
229 | kaminari (1.2.2)
230 | activesupport (>= 4.1.0)
231 | kaminari-actionview (= 1.2.2)
232 | kaminari-activerecord (= 1.2.2)
233 | kaminari-core (= 1.2.2)
234 | kaminari-actionview (1.2.2)
235 | actionview
236 | kaminari-core (= 1.2.2)
237 | kaminari-activerecord (1.2.2)
238 | activerecord
239 | kaminari-core (= 1.2.2)
240 | kaminari-core (1.2.2)
241 | keccak (1.3.1)
242 | konstructor (1.0.2)
243 | listen (3.8.0)
244 | rb-fsevent (~> 0.10, >= 0.10.3)
245 | rb-inotify (~> 0.9, >= 0.9.10)
246 | lograge (0.14.0)
247 | actionpack (>= 4)
248 | activesupport (>= 4)
249 | railties (>= 4)
250 | request_store (~> 1.0)
251 | loofah (2.22.0)
252 | crass (~> 1.0.2)
253 | nokogiri (>= 1.12.0)
254 | mail (2.8.1)
255 | mini_mime (>= 0.1.1)
256 | net-imap
257 | net-pop
258 | net-smtp
259 | marcel (1.0.2)
260 | marked-rails (9.1.2.0)
261 | matrix (0.4.2)
262 | memoist (0.16.2)
263 | meta-tags (2.20.0)
264 | actionpack (>= 6.0.0, < 7.2)
265 | method_source (1.0.0)
266 | mini_mime (1.1.5)
267 | mini_portile2 (2.8.5)
268 | minitest (5.21.1)
269 | multi_json (1.15.0)
270 | multi_xml (0.6.0)
271 | net-imap (0.3.7)
272 | date
273 | net-protocol
274 | net-pop (0.1.2)
275 | net-protocol
276 | net-protocol (0.2.1)
277 | timeout
278 | net-smtp (0.3.3)
279 | net-protocol
280 | nio4r (2.7.0)
281 | nokogiri (1.16.0)
282 | mini_portile2 (~> 2.8.2)
283 | racc (~> 1.4)
284 | omniauth (2.1.1)
285 | hashie (>= 3.4.6)
286 | rack (>= 2.2.3)
287 | rack-protection
288 | omniauth-rails_csrf_protection (1.0.1)
289 | actionpack (>= 4.2)
290 | omniauth (~> 2.0)
291 | omniauth_openid_connect (0.6.1)
292 | omniauth (>= 1.9, < 3)
293 | openid_connect (~> 1.1)
294 | openid_connect (1.4.2)
295 | activemodel
296 | attr_required (>= 1.0.0)
297 | json-jwt (>= 1.15.0)
298 | net-smtp
299 | rack-oauth2 (~> 1.21)
300 | swd (~> 1.3)
301 | tzinfo
302 | validate_email
303 | validate_url
304 | webfinger (~> 1.2)
305 | openssl (3.1.0)
306 | os (1.1.4)
307 | pagy (6.1.0)
308 | parser (3.2.2.1)
309 | ast (~> 2.4.1)
310 | pg (1.5.4)
311 | pkg-config (1.5.1)
312 | pry (0.14.2)
313 | coderay (~> 1.1)
314 | method_source (~> 1.0)
315 | pry-rails (0.3.9)
316 | pry (>= 0.10.4)
317 | psych (5.1.0)
318 | stringio
319 | public_suffix (5.0.3)
320 | puma (6.4.2)
321 | nio4r (~> 2.0)
322 | racc (1.7.3)
323 | rack (2.2.8)
324 | rack-oauth2 (1.21.3)
325 | activesupport
326 | attr_required
327 | httpclient
328 | json-jwt (>= 1.11.0)
329 | rack (>= 2.1.0)
330 | rack-protection (3.0.5)
331 | rack
332 | rack-test (2.1.0)
333 | rack (>= 1.3)
334 | rails (7.0.8)
335 | actioncable (= 7.0.8)
336 | actionmailbox (= 7.0.8)
337 | actionmailer (= 7.0.8)
338 | actionpack (= 7.0.8)
339 | actiontext (= 7.0.8)
340 | actionview (= 7.0.8)
341 | activejob (= 7.0.8)
342 | activemodel (= 7.0.8)
343 | activerecord (= 7.0.8)
344 | activestorage (= 7.0.8)
345 | activesupport (= 7.0.8)
346 | bundler (>= 1.15.0)
347 | railties (= 7.0.8)
348 | rails-dom-testing (2.2.0)
349 | activesupport (>= 5.0.0)
350 | minitest
351 | nokogiri (>= 1.6)
352 | rails-html-sanitizer (1.6.0)
353 | loofah (~> 2.21)
354 | nokogiri (~> 1.14)
355 | rails_12factor (0.0.3)
356 | rails_serve_static_assets
357 | rails_stdout_logging
358 | rails_serve_static_assets (0.0.5)
359 | rails_stdout_logging (0.0.5)
360 | railties (7.0.8)
361 | actionpack (= 7.0.8)
362 | activesupport (= 7.0.8)
363 | method_source
364 | rake (>= 12.2)
365 | thor (~> 1.0)
366 | zeitwerk (~> 2.5)
367 | rake (13.1.0)
368 | rb-fsevent (0.11.2)
369 | rb-inotify (0.10.1)
370 | ffi (~> 1.0)
371 | rb_sys (0.9.86)
372 | rbs (3.1.0)
373 | rbs_rails (0.12.0)
374 | parser
375 | rbs (>= 1)
376 | rbsecp256k1 (5.1.1)
377 | mini_portile2 (~> 2.8)
378 | pkg-config (~> 1.5)
379 | rubyzip (~> 2.3)
380 | rdoc (6.5.0)
381 | psych (>= 4.0.0)
382 | regexp_parser (2.8.1)
383 | request_store (1.5.1)
384 | rack (>= 1.4)
385 | rexml (3.2.6)
386 | ruby2_keywords (0.0.5)
387 | rubyzip (2.3.2)
388 | sass-rails (6.0.0)
389 | sassc-rails (~> 2.1, >= 2.1.1)
390 | sassc (2.4.0)
391 | ffi (~> 1.9)
392 | sassc-rails (2.1.2)
393 | railties (>= 4.0.0)
394 | sassc (>= 2.0)
395 | sprockets (> 3.0)
396 | sprockets-rails
397 | tilt
398 | scrypt (3.0.7)
399 | ffi-compiler (>= 1.0, < 2.0)
400 | sdoc (1.0.0)
401 | rdoc (>= 5.0)
402 | selenium-webdriver (4.14.0)
403 | rexml (~> 3.2, >= 3.2.5)
404 | rubyzip (>= 1.2.2, < 3.0)
405 | websocket (~> 1.0)
406 | signet (0.17.0)
407 | addressable (~> 2.8)
408 | faraday (>= 0.17.5, < 3.a)
409 | jwt (>= 1.5, < 3.0)
410 | multi_json (~> 1.10)
411 | sitemap_generator (6.3.0)
412 | builder (~> 3.0)
413 | siwe (2.0.0)
414 | eth (~> 0.5.1)
415 | slim (5.1.1)
416 | temple (~> 0.10.0)
417 | tilt (>= 2.1.0)
418 | slim-rails (3.6.3)
419 | actionpack (>= 3.1)
420 | railties (>= 3.1)
421 | slim (>= 3.0, < 6.0, != 5.0.0)
422 | sprockets (4.2.0)
423 | concurrent-ruby (~> 1.0)
424 | rack (>= 2.2.4, < 4)
425 | sprockets-rails (3.4.2)
426 | actionpack (>= 5.2)
427 | activesupport (>= 5.2)
428 | sprockets (>= 3.0.0)
429 | stackdriver (0.21.1)
430 | google-cloud-error_reporting (~> 0.41)
431 | google-cloud-logging (~> 2.1)
432 | google-cloud-trace (~> 0.40)
433 | stackdriver-core (1.5.0)
434 | google-cloud-core (~> 1.2)
435 | stringio (3.0.5)
436 | swd (1.3.0)
437 | activesupport (>= 3)
438 | attr_required (>= 0.0.5)
439 | httpclient (>= 2.4)
440 | temple (0.10.3)
441 | thor (1.3.0)
442 | tilt (2.3.0)
443 | timeout (0.4.0)
444 | turbo-rails (1.0.1)
445 | actionpack (>= 6.0.0)
446 | railties (>= 6.0.0)
447 | tzinfo (2.0.6)
448 | concurrent-ruby (~> 1.0)
449 | uglifier (4.2.0)
450 | execjs (>= 0.3.0, < 3)
451 | validate_email (0.1.6)
452 | activemodel (>= 3.0)
453 | mail (>= 2.2.5)
454 | validate_url (1.0.15)
455 | activemodel (>= 3.0.0)
456 | public_suffix
457 | view_component (3.10.0)
458 | activesupport (>= 5.2.0, < 8.0)
459 | concurrent-ruby (~> 1.0)
460 | method_source (~> 1.0)
461 | webfinger (1.2.0)
462 | activesupport
463 | httpclient (>= 2.4)
464 | websocket (1.2.10)
465 | websocket-driver (0.7.6)
466 | websocket-extensions (>= 0.1.0)
467 | websocket-extensions (0.1.5)
468 | xpath (3.2.0)
469 | nokogiri (~> 1.8)
470 | zeitwerk (2.6.12)
471 |
472 | PLATFORMS
473 | ruby
474 |
475 | DEPENDENCIES
476 | avo
477 | byebug
478 | capybara
479 | commonmarker
480 | graphiql-rails
481 | graphql
482 | jbuilder
483 | kaminari
484 | listen
485 | lograge
486 | marked-rails
487 | meta-tags
488 | omniauth-rails_csrf_protection
489 | omniauth-siwe!
490 | pg
491 | pry-rails
492 | puma
493 | rails (~> 7.0.0)
494 | rails_12factor
495 | rbs_rails
496 | sass-rails
497 | sdoc (~> 1.0.0)
498 | selenium-webdriver
499 | sitemap_generator
500 | slim-rails
501 | stackdriver
502 | turbo-rails (~> 1.0.0)
503 | uglifier
504 |
505 | BUNDLED WITH
506 | 2.1.4
507 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Kenichi Takahashi
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.rdoc:
--------------------------------------------------------------------------------
1 | == README
2 |
3 | This README would normally document whatever steps are necessary to get the
4 | application up and running.
5 |
6 | Things you may want to cover:
7 |
8 | * Ruby version
9 |
10 | * System dependencies
11 |
12 | * Configuration
13 |
14 | * Database creation
15 |
16 | * Database initialization
17 |
18 | * How to run the test suite
19 |
20 | * Services (job queues, cache servers, search engines, etc.)
21 |
22 | * Deployment instructions
23 |
24 | * ...
25 |
26 |
27 | Please feel free to use a different markup language if you do not plan to run
28 | rake doc:app.
29 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | # Add your own tasks in files placed in lib/tasks ending in .rake,
2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3 |
4 | require_relative 'config/application'
5 |
6 | Rails.application.load_tasks
7 |
--------------------------------------------------------------------------------
/Steepfile:
--------------------------------------------------------------------------------
1 | target :app do
2 | check "app/models"
3 | signature "sig"
4 | repo_path "vendor/rbs/gem_rbs_collection/gems"
5 |
6 | library 'pathname'
7 | library 'logger'
8 | library 'mutex_m'
9 | library 'date'
10 | library 'monitor'
11 | library 'singleton'
12 | library 'tsort'
13 | library 'securerandom'
14 | library 'base64'
15 | library 'forwardable'
16 | library 'time'
17 | library 'json'
18 |
19 | library 'rack'
20 |
21 | library 'activesupport'
22 | library 'actionpack'
23 | library 'activejob'
24 | library 'activemodel'
25 | library 'actionview'
26 | library 'activerecord'
27 | library 'railties'
28 | end
29 |
--------------------------------------------------------------------------------
/app/assets/config/manifest.js:
--------------------------------------------------------------------------------
1 | //= link_tree ../images
2 | //= link_directory ../javascripts .js
3 | //= link_directory ../stylesheets .css
4 |
--------------------------------------------------------------------------------
/app/assets/images/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenchan/tdnm_blog/2aa48ea6eaff17758f5477a8a638671e94275fae/app/assets/images/.keep
--------------------------------------------------------------------------------
/app/assets/javascripts/application.js:
--------------------------------------------------------------------------------
1 | // This is a manifest file that'll be compiled into application.js, which will include all the files
2 | // listed below.
3 | //
4 | // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, or any plugin's
5 | // vendor/assets/javascripts directory can be referenced here using a relative path.
6 | //
7 | // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8 | // compiled file. JavaScript code in this file should be added after the last require_* statement.
9 | //
10 | // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
11 | // about supported directives.
12 | //
13 | //= require rails-ujs
14 | //= require_tree .
15 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/_articles.scss:
--------------------------------------------------------------------------------
1 | .article-grid-card {
2 | height: 30rem;
3 | overflow: hidden;
4 | color: var(--base-font-color);
5 | }
6 | .mdc-card .card-header, .card-text {
7 | padding: 0rem 1rem;
8 | }
9 | .right {
10 | text-align: right;
11 | }
12 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/_base.scss:
--------------------------------------------------------------------------------
1 | :root {
2 | --mdc-typography-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Hiragino Sans', 'BIZ UDPGothic', sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Sans Emoji";
3 | --mdc-typography-body2-line-height: 1.5rem;
4 | --mdc-theme-primary: #003529;
5 |
6 | --base-font-color: #333;
7 | --link-text-color: #1D7FAF;
8 | --link-text-color__hover: #62A3C4;
9 | }
10 |
11 | .mdc-top-app-bar__title a {
12 | color: white;
13 | &:hover {
14 | color: #CCCCCC;
15 | }
16 | }
17 |
18 | body {
19 | color: var(--base-font-color);
20 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Hiragino Sans', 'BIZ UDPGothic', sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Sans Emoji";
21 | margin: 0;
22 | line-height: 1.5rem;
23 | }
24 |
25 | img, embed, object, video {
26 | max-width: 100%;
27 | }
28 |
29 | footer {
30 | width: 100%;
31 | height: 20px;
32 | }
33 |
34 | a {
35 | overflow-wrap: break-word;
36 | color: var(--link-text-color);
37 | text-decoration: none;
38 | transition: 0.3s;
39 | &:hover {
40 | color: var(--link-text-color__hover);
41 | }
42 | }
43 |
44 | .pagination {
45 | margin: 1rem;
46 | font-size: large;
47 | }
48 |
49 | .main-article {
50 | margin: 0px auto;
51 | width: 100%;
52 |
53 | @media screen and (min-width: 768px) {
54 | width: 600px;
55 | }
56 | @media screen and (min-width: 1025px) {
57 | width: 800px;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/admin/articles.scss:
--------------------------------------------------------------------------------
1 | code {
2 | background-color: #f0f0f0;
3 | padding: 0.2em;
4 | border-radius: 4px;
5 | font-family: monospace, "Noto Sans", "Noto Sans CJK JP", sans-serif;
6 | }
7 | pre > code {
8 | display: block;
9 | border: none;
10 | line-height: 1.6em;
11 | padding: 0.5em;
12 | overflow-x: auto;
13 | }
14 |
15 | .site_header {
16 | z-index: 100;
17 | top: 0;
18 | position: sticky;
19 | height: 3.5rem;
20 | border-bottom: 1px solid #cacaca;
21 | color: #1a455a;
22 | background: #dfebfd;
23 | font-weight: 700;
24 | display: flex;
25 | align-items: center;
26 | }
27 | .site_header__title {
28 | margin: 0 auto 0;
29 | font-size: 1.2rem;
30 | text-decoration: none;
31 | color: inherit;
32 | }
33 | .article {
34 | border-top: 1px solid #bbb;
35 | margin-bottom: 1rem;
36 | }
37 | main .article:first-child {
38 | border: none;
39 | }
40 | .article__title {
41 | margin-top: 0;
42 | padding-top: 0;
43 | font-size: 1.7rem;
44 | font-weight: 700;
45 | line-height: 2.5rem;
46 | }
47 | .article__published_on {
48 | padding: 0;
49 | font-size: 0.75rem;
50 | color: #777;
51 | }
52 | .article__body {
53 | margin-top: 1.5rem;
54 | margin-bottom: 2rem;
55 | color: #545454;
56 | line-height: 1.7em;
57 | }
58 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/application.scss:
--------------------------------------------------------------------------------
1 | @import "base";
2 | @import "articles";
3 |
--------------------------------------------------------------------------------
/app/avo/resources/article_resource.rb:
--------------------------------------------------------------------------------
1 | class ArticleResource < Avo::BaseResource
2 | self.title = :id
3 | self.includes = []
4 | # self.search_query = ->(params:) do
5 | # scope.ransack(id_eq: params[:q], m: "or").result(distinct: false)
6 | # end
7 |
8 | field :id, as: :id
9 | field :title, as: :text, format_using: -> (value) { value&.truncate 20 }
10 | field :body, as: :markdown
11 | field :slug, as: :text
12 | field :published_on, as: :date
13 | field :draft, as: :boolean
14 | field :featured_image_url, as: :external_image
15 | # add fields here
16 | end
17 |
--------------------------------------------------------------------------------
/app/controllers/application_controller.rb:
--------------------------------------------------------------------------------
1 | class ApplicationController < ActionController::Base
2 | protect_from_forgery with: :exception
3 | end
4 |
--------------------------------------------------------------------------------
/app/controllers/articles_controller.rb:
--------------------------------------------------------------------------------
1 | class ArticlesController < ApplicationController
2 | layout 'application'
3 |
4 | def index
5 | @articles = Article.published.order(published_on: :desc).page(params[:page]).per(params[:per_page] || 12)
6 | end
7 |
8 | def show
9 | if params[:year]
10 | year, month, day = params.values_at(:year, :month, :day).map(&:to_i)
11 | slug = params[:slug]
12 | @article = Article.published.where(published_on: Date.new(year, month, day), slug: slug).first!
13 |
14 | redirect_to article_path(title: @article.title), status: 301
15 | return
16 | end
17 |
18 | @article = Article.published.where(title: params[:title]).first!
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/app/controllers/avo/articles_controller.rb:
--------------------------------------------------------------------------------
1 | class Avo::ArticlesController < Avo::ResourcesController
2 | end
3 |
--------------------------------------------------------------------------------
/app/controllers/concerns/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenchan/tdnm_blog/2aa48ea6eaff17758f5477a8a638671e94275fae/app/controllers/concerns/.keep
--------------------------------------------------------------------------------
/app/controllers/graphql_controller.rb:
--------------------------------------------------------------------------------
1 | class GraphqlController < ApplicationController
2 | protect_from_forgery with: :null_session
3 |
4 | def execute
5 | variables = ensure_hash(params[:variables])
6 | query = params[:query]
7 | operation_name = params[:operationName]
8 | context = {
9 | # Query context goes here, for example:
10 | # current_user: current_user,
11 | }
12 | result = TdnmSchema.execute(query, variables: variables, context: context, operation_name: operation_name)
13 | render json: result
14 | rescue => e
15 | raise e unless Rails.env.development?
16 | handle_error_in_development e
17 | end
18 |
19 | private
20 |
21 | # Handle form data, JSON body, or a blank value
22 | def ensure_hash(ambiguous_param)
23 | case ambiguous_param
24 | when String
25 | if ambiguous_param.present?
26 | ensure_hash(JSON.parse(ambiguous_param))
27 | else
28 | {}
29 | end
30 | when Hash, ActionController::Parameters
31 | ambiguous_param
32 | when nil
33 | {}
34 | else
35 | raise ArgumentError, "Unexpected parameter: #{ambiguous_param}"
36 | end
37 | end
38 |
39 | def handle_error_in_development(e)
40 | logger.error e.message
41 | logger.error e.backtrace.join("\n")
42 |
43 | render json: { error: { message: e.message, backtrace: e.backtrace }, data: {} }, status: 500
44 | end
45 | end
46 |
--------------------------------------------------------------------------------
/app/controllers/sessions_controller.rb:
--------------------------------------------------------------------------------
1 | class SessionsController < ApplicationController
2 | def new
3 | end
4 |
5 | def create
6 | reset_session
7 |
8 | session[:user_id] = request.env['omniauth.auth']['uid']
9 |
10 | redirect_to '/avo'
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/app/graphql/mutations/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenchan/tdnm_blog/2aa48ea6eaff17758f5477a8a638671e94275fae/app/graphql/mutations/.keep
--------------------------------------------------------------------------------
/app/graphql/tdnm_schema.rb:
--------------------------------------------------------------------------------
1 | class TdnmSchema < GraphQL::Schema
2 | mutation(Types::MutationType)
3 | query(Types::QueryType)
4 | end
5 |
--------------------------------------------------------------------------------
/app/graphql/types/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenchan/tdnm_blog/2aa48ea6eaff17758f5477a8a638671e94275fae/app/graphql/types/.keep
--------------------------------------------------------------------------------
/app/graphql/types/article_type.rb:
--------------------------------------------------------------------------------
1 | module Types
2 | class ArticleType < Types::BaseObject
3 | field :id, ID, null: false
4 | field :title, String, null: false
5 | field :body, String, null: false
6 | field :slug, String, null: false
7 | field :published_on, GraphQL::Types::ISO8601DateTime, null: false
8 | field :created_at, GraphQL::Types::ISO8601DateTime, null: false
9 | field :updated_at, GraphQL::Types::ISO8601DateTime, null: false
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/app/graphql/types/base_enum.rb:
--------------------------------------------------------------------------------
1 | module Types
2 | class BaseEnum < GraphQL::Schema::Enum
3 | end
4 | end
5 |
--------------------------------------------------------------------------------
/app/graphql/types/base_input_object.rb:
--------------------------------------------------------------------------------
1 | module Types
2 | class BaseInputObject < GraphQL::Schema::InputObject
3 | end
4 | end
5 |
--------------------------------------------------------------------------------
/app/graphql/types/base_interface.rb:
--------------------------------------------------------------------------------
1 | module Types
2 | module BaseInterface
3 | include GraphQL::Schema::Interface
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/app/graphql/types/base_object.rb:
--------------------------------------------------------------------------------
1 | module Types
2 | class BaseObject < GraphQL::Schema::Object
3 | end
4 | end
5 |
--------------------------------------------------------------------------------
/app/graphql/types/base_scalar.rb:
--------------------------------------------------------------------------------
1 | module Types
2 | class BaseScalar < GraphQL::Schema::Scalar
3 | end
4 | end
5 |
--------------------------------------------------------------------------------
/app/graphql/types/base_union.rb:
--------------------------------------------------------------------------------
1 | module Types
2 | class BaseUnion < GraphQL::Schema::Union
3 | end
4 | end
5 |
--------------------------------------------------------------------------------
/app/graphql/types/mutation_type.rb:
--------------------------------------------------------------------------------
1 | module Types
2 | class MutationType < Types::BaseObject
3 | # TODO: remove me
4 | field :test_field, String, null: false,
5 | description: "An example field added by the generator"
6 | def test_field
7 | "Hello World"
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/app/graphql/types/query_type.rb:
--------------------------------------------------------------------------------
1 | module Types
2 | class QueryType < Types::BaseObject
3 | # Add root-level fields here.
4 | # They will be entry points for queries on your schema.
5 |
6 | field :article, Types::ArticleType, null: true do
7 | description 'Find a article'
8 | argument :id, ID, required: false
9 | argument :slug, String, required: false
10 | end
11 |
12 | field :articles, Types::ArticleType.connection_type, null: false, max_page_size: 100 do
13 | description 'List articles'
14 | argument :published_on, String, required: false
15 | end
16 |
17 | def article(id: nil, slug: nil)
18 | if id
19 | Article.find(id)
20 | else
21 | Article.where(title: slug).first
22 | end
23 | end
24 |
25 | def articles(published_on: nil)
26 | if published_on
27 | Article.where(published_on: published_on)
28 | else
29 | Article.order(published_on: :desc)
30 | end
31 | end
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/app/helpers/application_helper.rb:
--------------------------------------------------------------------------------
1 | module ApplicationHelper
2 | def weblog
3 | @_weblog ||= Weblog.first
4 | end
5 |
6 | def meta_description
7 | @_meta_description ||= if @article
8 | truncate(
9 | strip_tags(Commonmarker.to_html(@article.body)),
10 | length: MetaTags.config.description_limit
11 | )
12 | else
13 | nil
14 | end
15 | end
16 |
17 | def default_meta_tags
18 | {
19 | site: weblog.title,
20 | charset: 'utf-8',
21 | title: @article.try(:title),
22 | reverse: true,
23 | description: meta_description,
24 | og: {
25 | title: @article.try(:title),
26 | site_name: weblog.title,
27 | image: @article.try(:featured_image_url).blank? ? weblog.default_featured_image_url : @article.featured_image_url,
28 | description: meta_description,
29 | url: @article ? article_path(title: @article.title, only_path: false) : root_url(only_path: false),
30 | type: @article ? 'article' : 'website'
31 | },
32 | twitter: {
33 | card: "summary"
34 | }
35 | }
36 | end
37 | end
38 |
--------------------------------------------------------------------------------
/app/helpers/articles_helper.rb:
--------------------------------------------------------------------------------
1 | module ArticlesHelper
2 |
3 | end
4 |
--------------------------------------------------------------------------------
/app/jobs/application_job.rb:
--------------------------------------------------------------------------------
1 | class ApplicationJob < ActiveJob::Base
2 | end
3 |
--------------------------------------------------------------------------------
/app/mailers/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenchan/tdnm_blog/2aa48ea6eaff17758f5477a8a638671e94275fae/app/mailers/.keep
--------------------------------------------------------------------------------
/app/models/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenchan/tdnm_blog/2aa48ea6eaff17758f5477a8a638671e94275fae/app/models/.keep
--------------------------------------------------------------------------------
/app/models/application_record.rb:
--------------------------------------------------------------------------------
1 | class ApplicationRecord < ActiveRecord::Base
2 | self.abstract_class = true
3 | end
4 |
--------------------------------------------------------------------------------
/app/models/article.rb:
--------------------------------------------------------------------------------
1 | class Article < ApplicationRecord
2 | scope :published, -> { where(draft: false) }
3 | scope :drafts, -> { where(draft: true) }
4 | end
5 |
--------------------------------------------------------------------------------
/app/models/concerns/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenchan/tdnm_blog/2aa48ea6eaff17758f5477a8a638671e94275fae/app/models/concerns/.keep
--------------------------------------------------------------------------------
/app/models/weblog.rb:
--------------------------------------------------------------------------------
1 | class Weblog < ApplicationRecord
2 | end
3 |
--------------------------------------------------------------------------------
/app/views/articles/index.atom.builder:
--------------------------------------------------------------------------------
1 | atom_feed(language: 'ja_JP') do |feed|
2 | feed.title(weblog.title)
3 | feed.updated(@articles[0].created_at) if @articles.length > 0
4 |
5 | @articles.each do |a|
6 | feed.entry(a, url: article_url(title: a.title, only_path: false)) do |entry|
7 | entry.title(a.title)
8 | entry.content(
9 | (a.featured_image_url.present? ? "" : '') +
10 | Commonmarker.to_html(a.body, options: { render: { unsafe: true } }), type: 'html'
11 | )
12 |
13 | entry.author do |author|
14 | author.name("Kenichi TAKAHASHI")
15 | end
16 | end
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/app/views/articles/index.html.slim:
--------------------------------------------------------------------------------
1 | .mdc-layout-grid
2 | .mdc-layout-grid__inner
3 | - @articles.each do |a|
4 | .mdc-layout-grid__cell--span-4
5 | a href="#{article_path(title: a.title)}"
6 | article.mdc-card.article-grid-card.mdc-ripple-surface.mdc-elevation--z3
7 | header.card-header
8 | h2= a.title
9 | - if a.featured_image_url?
10 | .mdc-card__media.mdc-card__media--16-9 style="background-image: url(#{a.featured_image_url});"
11 |
12 | .card-text== sanitize(Commonmarker.to_html(a.body, options: { render: { unsafe: true} }), tags: %w(p br))
13 | .mdc-layout-grid__inner
14 | .mdc-layout-grid__cell--span-12 style="display: flex; justify-content: center;"
15 | = paginate @articles
16 |
--------------------------------------------------------------------------------
/app/views/articles/show.html.slim:
--------------------------------------------------------------------------------
1 | .mdc-layout-grid.main-article
2 | .mdc-layout-grid__inner
3 | .mdc-layout-grid__cell--span-4-phone.mdc-layout-grid__cell--span-12-desktop.mdc-layout-grid__cell--span-8-tablet.mdc-elevation--z3
4 | article.mdc-card
5 | header.card-header
6 | h2= @article.title
7 | - if @article.featured_image_url?
8 | .mdc-card__media.mdc-card__media--16-9 style="background-image: url(#{@article.featured_image_url});"
9 |
10 | .card-text
11 | == Commonmarker.to_html(@article.body, options: { render: { unsafe: true} })
12 | .right
13 | = "created_at: "
14 | == @article.created_at
15 | .right
16 | = "updated_at: "
17 | == @article.created_at
18 |
--------------------------------------------------------------------------------
/app/views/kaminari/_first_page.html.slim:
--------------------------------------------------------------------------------
1 | / Link to the "First" page
2 | - available local variables
3 | url : url to the first page
4 | current_page : a page object for the currently displayed page
5 | total_pages : total number of pages
6 | per_page : number of items to fetch per page
7 | remote : data-remote
8 | span.first
9 | == link_to_unless current_page.first?, t('views.pagination.first').html_safe, url, :remote => remote
10 | '
11 |
--------------------------------------------------------------------------------
/app/views/kaminari/_gap.html.slim:
--------------------------------------------------------------------------------
1 | / Non-link tag that stands for skipped pages...
2 | - available local variables
3 | current_page : a page object for the currently displayed page
4 | total_pages : total number of pages
5 | per_page : number of items to fetch per page
6 | remote : data-remote
7 | span.page.gap
8 | == t('views.pagination.truncate').html_safe
9 | '
10 |
--------------------------------------------------------------------------------
/app/views/kaminari/_last_page.html.slim:
--------------------------------------------------------------------------------
1 | / Link to the "Last" page
2 | - available local variables
3 | url : url to the last page
4 | current_page : a page object for the currently displayed page
5 | total_pages : total number of pages
6 | per_page : number of items to fetch per page
7 | remote : data-remote
8 | span.last
9 | == link_to_unless current_page.last?, t('views.pagination.last').html_safe, url, :remote => remote
10 | '
11 |
--------------------------------------------------------------------------------
/app/views/kaminari/_next_page.html.slim:
--------------------------------------------------------------------------------
1 | / Link to the "Next" page
2 | - available local variables
3 | url : url to the next page
4 | current_page : a page object for the currently displayed page
5 | total_pages : total number of pages
6 | per_page : number of items to fetch per page
7 | remote : data-remote
8 | span.next
9 | == link_to_unless current_page.last?, t('views.pagination.next').html_safe, url, :rel => 'next', :remote => remote
10 | '
11 |
--------------------------------------------------------------------------------
/app/views/kaminari/_page.html.slim:
--------------------------------------------------------------------------------
1 | / Link showing page number
2 | - available local variables
3 | page : a page object for "this" page
4 | url : url to this page
5 | current_page : a page object for the currently displayed page
6 | total_pages : total number of pages
7 | per_page : number of items to fetch per page
8 | remote : data-remote
9 | span class="page#{' current' if page.current?}"
10 | == link_to_unless page.current?, page, url, {:remote => remote, :rel => page.next? ? 'next' : page.prev? ? 'prev' : nil}
11 | '
12 |
--------------------------------------------------------------------------------
/app/views/kaminari/_paginator.html.slim:
--------------------------------------------------------------------------------
1 | / The container tag
2 | - available local variables
3 | current_page : a page object for the currently displayed page
4 | total_pages : total number of pages
5 | per_page : number of items to fetch per page
6 | remote : data-remote
7 | paginator : the paginator that renders the pagination tags inside
8 |
9 | == paginator.render do
10 | nav.pagination
11 | == first_page_tag unless current_page.first?
12 | == prev_page_tag unless current_page.first?
13 | - each_page do |page|
14 | - if page.left_outer? || page.right_outer? || page.inside_window?
15 | == page_tag page
16 | - elsif !page.was_truncated?
17 | == gap_tag
18 | == next_page_tag unless current_page.last?
19 | == last_page_tag unless current_page.last?
20 |
--------------------------------------------------------------------------------
/app/views/kaminari/_prev_page.html.slim:
--------------------------------------------------------------------------------
1 | / Link to the "Previous" page
2 | - available local variables
3 | url : url to the previous page
4 | current_page : a page object for the currently displayed page
5 | total_pages : total number of pages
6 | per_page : number of items to fetch per page
7 | remote : data-remote
8 | span.prev
9 | == link_to_unless current_page.first?, t('views.pagination.previous').html_safe, url, :rel => 'prev', :remote => remote
10 | '
11 |
--------------------------------------------------------------------------------
/app/views/layouts/application.html.slim:
--------------------------------------------------------------------------------
1 | doctype html
2 |
3 | html
4 | head
5 | = display_meta_tags default_meta_tags
6 | meta http-equiv='X-UA-Compatible' content='IE=edge;chrome=1'
7 | meta name='viewport' content='width=device-width, initial-scale=1.0'
8 |
9 | link rel='alternate' type='application/atom+xml' title='atom' href='/atom.xml'
10 |
11 | link href="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.css" rel="stylesheet"
12 | script src="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.js"
13 |
14 | link rel="stylesheet" href='https://cdnjs.cloudflare.com/ajax/libs/prism/1.23.0/themes/prism.min.css'
15 | script async=true src='https://cdnjs.cloudflare.com/ajax/libs/prism/1.23.0/components/prism-core.min.js'
16 | script async=true src='https://cdnjs.cloudflare.com/ajax/libs/prism/1.23.0/plugins/autoloader/prism-autoloader.min.js'
17 |
18 | = stylesheet_link_tag 'application', media: 'all'
19 | = turbo_include_tags
20 |
21 | body
22 | #root
23 | header.mdc-top-app-bar.mdc-top-app-bar--fixed
24 | .mdc-top-app-bar__row
25 | section.mdc-top-app-bar__section
26 | .mdc-top-app-bar__title= link_to weblog.title, root_path
27 | main.mdc-top-app-bar--fixed-adjust
28 | == yield
29 | footer
30 |
--------------------------------------------------------------------------------
/app/views/sessions/new.html.slim:
--------------------------------------------------------------------------------
1 | - if flash[:notice]
2 | = flash[:notice]
3 |
4 | = form_tag '/auth/siwe', method: 'post', data: {turbo: false}
5 | = submit_tag 'Sign-in With Ethereum'
6 |
--------------------------------------------------------------------------------
/bin/bundle:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
3 | load Gem.bin_path('bundler', 'bundle')
4 |
--------------------------------------------------------------------------------
/bin/rails:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | APP_PATH = File.expand_path("../config/application", __dir__)
3 | require_relative "../config/boot"
4 | require "rails/commands"
5 |
--------------------------------------------------------------------------------
/bin/rake:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require_relative "../config/boot"
3 | require "rake"
4 | Rake.application.run
5 |
--------------------------------------------------------------------------------
/bin/render-build.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | # exit on error
3 | set -o errexit
4 |
5 | bundle install --deployment
6 | bundle exec rake assets:precompile
7 | bundle exec rake assets:clean
8 | bundle exec rake db:migrate
9 |
--------------------------------------------------------------------------------
/bin/setup:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require "fileutils"
3 |
4 | # path to your application root.
5 | APP_ROOT = File.expand_path("..", __dir__)
6 |
7 | def system!(*args)
8 | system(*args) || abort("\n== Command #{args} failed ==")
9 | end
10 |
11 | FileUtils.chdir APP_ROOT do
12 | # This script is a way to set up or update your development environment automatically.
13 | # This script is idempotent, so that you can run it at any time and get an expectable outcome.
14 | # Add necessary setup steps to this file.
15 |
16 | puts "== Installing dependencies =="
17 | system! "gem install bundler --conservative"
18 | system("bundle check") || system!("bundle install")
19 |
20 | # puts "\n== Copying sample files =="
21 | # unless File.exist?("config/database.yml")
22 | # FileUtils.cp "config/database.yml.sample", "config/database.yml"
23 | # end
24 |
25 | puts "\n== Preparing database =="
26 | system! "bin/rails db:prepare"
27 |
28 | puts "\n== Removing old logs and tempfiles =="
29 | system! "bin/rails log:clear tmp:clear"
30 |
31 | puts "\n== Restarting application server =="
32 | system! "bin/rails restart"
33 | end
34 |
--------------------------------------------------------------------------------
/bin/start:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -xe
4 |
5 | bin/rails assets:precompile;
6 | bin/rails db:migrate
7 |
8 | bin/rails s -b 0.0.0.0;
9 |
--------------------------------------------------------------------------------
/bin/steep:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | load Gem.bin_path('steep', 'steep')
3 |
--------------------------------------------------------------------------------
/bin/yarn:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | APP_ROOT = File.expand_path('..', __dir__)
3 | Dir.chdir(APP_ROOT) do
4 | yarn = ENV["PATH"].split(File::PATH_SEPARATOR).
5 | select { |dir| File.expand_path(dir) != __dir__ }.
6 | product(["yarn", "yarn.cmd", "yarn.ps1"]).
7 | map { |dir, file| File.expand_path(file, dir) }.
8 | find { |file| File.executable?(file) }
9 |
10 | if yarn
11 | exec yarn, *ARGV
12 | else
13 | $stderr.puts "Yarn executable was not detected in the system."
14 | $stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install"
15 | exit 1
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/config.ru:
--------------------------------------------------------------------------------
1 | # This file is used by Rack-based servers to start the application.
2 |
3 | require_relative "config/environment"
4 |
5 | run Rails.application
6 | Rails.application.load_server
7 |
--------------------------------------------------------------------------------
/config/application.rb:
--------------------------------------------------------------------------------
1 | require_relative "boot"
2 |
3 | require "rails/all"
4 |
5 | # Require the gems listed in Gemfile, including any gems
6 | # you've limited to :test, :development, or :production.
7 | Bundler.require(*Rails.groups)
8 |
9 | module Tdnm
10 | class Application < Rails::Application
11 | # Initialize configuration defaults for originally generated Rails version.
12 | config.load_defaults 7.0
13 |
14 | # Configuration for the application, engines, and railties goes here.
15 | #
16 | # These settings can be overridden in specific environments using the files
17 | # in config/environments, which are processed later.
18 | #
19 | config.time_zone = "Tokyo"
20 | config.active_record.default_timezone = :local
21 | # config.eager_load_paths << Rails.root.join("extras")
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/config/boot.rb:
--------------------------------------------------------------------------------
1 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
2 |
3 | require "bundler/setup" # Set up gems listed in the Gemfile.
4 |
--------------------------------------------------------------------------------
/config/cable.yml:
--------------------------------------------------------------------------------
1 | development:
2 | adapter: redis
3 | url: redis://localhost:6379/1
4 |
5 | test:
6 | adapter: test
7 |
8 | production:
9 | adapter: redis
10 | url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
11 | channel_prefix: tdnm_production
12 |
--------------------------------------------------------------------------------
/config/credentials.yml.enc:
--------------------------------------------------------------------------------
1 | EMG+s1OHyq/26v+33qI2Gpvlb22TvGKBScyBxm9OdUR3iZSWx8a0GoDRQ62tRMecMkxXUFeCb1hc5HmJEkwU/rd21haF5RmOKmgAviVuYM5cp0y5uc+1DKf1E0+KLoe9JLM6ykJxwh7+OZTa07/q5bul728tNmuEDlW14jE7jp61q6C6L/k/QOfW9IZvTN6/SagGwu+NXuBquJZsm4qzo8YMcp/2Lq5zTaY8qEz2VsrqAwFlcVU0r9G63BPxlSs6P8dNkOVwpw6ePPklsNfHsD26w+WIKRy1zCToanVpzIYQoqZKRuobwQ0P5l6Kl8VcLTwa4ZtweEOXVh+P5FN9kyLdrod62h2OmegDrTbcm0TcDoZKORtifNdBB14/Xg9OLiEdtIpJuGxX4BT/6fgNAlRGZixiCU58qQP008Qrc5KVA+Gz5e5bE213f+UXj/LD1uKP3a41xfHlAijlZBmTVQcCb7ab7Ka1rAG2N5LPs1/ko13mWKBQBQQoRIKTQ3i93omMB2D0iv5xNrkBfcjkDGfLLb9F9xcy+E7ATLaO7vjk0aVMCt2/yR4Ibd+dAIaOjSifja4ydmYoNMe5KgNf3A0C3oPo5aMbLb298SxoHVqnRdxzxYWVAlb09B9EdiTKOtFTr03F+hsESdXIrK4u40X4h1iEbTy4leqDL+JyaiYy/D6Q8f1G0GR6sNbS8UNQ0bDXO41+/IlWBHv64SaZNeCUddMpeLWfqWBWR1vGkniecLXgfvA7pg/OnnUQbsLl7P9kt7i0d3AYC/9LfgWWHQ==--dGMdh9kGtUuR1ZwL--FRXruT78ATH56ZTdo3Qjhg==
--------------------------------------------------------------------------------
/config/database.yml:
--------------------------------------------------------------------------------
1 | # SQLite version 3.x
2 | # gem install sqlite3
3 | #
4 | # Ensure the SQLite 3 gem is defined in your Gemfile
5 | # gem 'sqlite3'
6 | #
7 | default: &default
8 | adapter: postgresql
9 | username: <%= ENV.fetch('DATABASE_USERNAME', 'postgres') %>
10 | password: <%= ENV.fetch('DATABASE_PASSWORD', '') %>
11 | host: <%= ENV.fetch('DATABASE_HOST', '127.0.0.1') %>
12 | port: <%= ENV.fetch('DATABASE_PORT', '5432') %>
13 | pool: 5
14 | timeout: 5000
15 | encoding: UTF8
16 |
17 | development:
18 | <<: *default
19 | database: tdnm
20 |
21 | # Warning: The database defined as "test" will be erased and
22 | # re-generated from your development database when you run "rake".
23 | # Do not set this db to the same as development or production.
24 | test:
25 | <<: *default
26 | database: tdnm_test
27 |
28 | production:
29 | <<: *default
30 | database: tdnm_production
31 |
--------------------------------------------------------------------------------
/config/environment.rb:
--------------------------------------------------------------------------------
1 | # Load the Rails application.
2 | require_relative "application"
3 |
4 | # Initialize the Rails application.
5 | Rails.application.initialize!
6 |
--------------------------------------------------------------------------------
/config/environments/development.rb:
--------------------------------------------------------------------------------
1 | require "active_support/core_ext/integer/time"
2 |
3 | Rails.application.configure do
4 | # Settings specified here will take precedence over those in config/application.rb.
5 |
6 | # In the development environment your application's code is reloaded any time
7 | # it changes. This slows down response time but is perfect for development
8 | # since you don't have to restart the web server when you make code changes.
9 | config.cache_classes = false
10 |
11 | # Do not eager load code on boot.
12 | config.eager_load = false
13 |
14 | # Show full error reports.
15 | config.consider_all_requests_local = true
16 |
17 | # Enable/disable caching. By default caching is disabled.
18 | # Run rails dev:cache to toggle caching.
19 | if Rails.root.join("tmp/caching-dev.txt").exist?
20 | config.action_controller.perform_caching = true
21 | config.action_controller.enable_fragment_cache_logging = true
22 |
23 | config.cache_store = :memory_store
24 | config.public_file_server.headers = {
25 | "Cache-Control" => "public, max-age=#{2.days.to_i}"
26 | }
27 | else
28 | config.action_controller.perform_caching = false
29 |
30 | config.cache_store = :null_store
31 | end
32 |
33 | # Store uploaded files on the local file system (see config/storage.yml for options).
34 | config.active_storage.service = :local
35 |
36 | # Don't care if the mailer can't send.
37 | config.action_mailer.raise_delivery_errors = false
38 |
39 | config.action_mailer.perform_caching = false
40 |
41 | # Print deprecation notices to the Rails logger.
42 | config.active_support.deprecation = :log
43 |
44 | # Raise exceptions for disallowed deprecations.
45 | config.active_support.disallowed_deprecation = :raise
46 |
47 | # Tell Active Support which deprecation messages to disallow.
48 | config.active_support.disallowed_deprecation_warnings = []
49 |
50 | # Raise an error on page load if there are pending migrations.
51 | config.active_record.migration_error = :page_load
52 |
53 | # Highlight code that triggered database queries in logs.
54 | config.active_record.verbose_query_logs = true
55 |
56 | # Suppress logger output for asset requests.
57 | config.assets.quiet = true
58 |
59 | # Raises error for missing translations.
60 | # config.i18n.raise_on_missing_translations = true
61 |
62 | # Annotate rendered view with file names.
63 | # config.action_view.annotate_rendered_view_with_filenames = true
64 |
65 | # Uncomment if you wish to allow Action Cable access from any origin.
66 | # config.action_cable.disable_request_forgery_protection = true
67 | end
68 |
--------------------------------------------------------------------------------
/config/environments/production.rb:
--------------------------------------------------------------------------------
1 | require "active_support/core_ext/integer/time"
2 |
3 | Rails.application.configure do
4 | # Settings specified here will take precedence over those in config/application.rb.
5 |
6 | # Code is not reloaded between requests.
7 | config.cache_classes = true
8 |
9 | # Eager load code on boot. This eager loads most of Rails and
10 | # your application in memory, allowing both threaded web servers
11 | # and those relying on copy on write to perform better.
12 | # Rake tasks automatically ignore this option for performance.
13 | config.eager_load = true
14 |
15 | # Full error reports are disabled and caching is turned on.
16 | config.consider_all_requests_local = false
17 | config.action_controller.perform_caching = true
18 |
19 | # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"]
20 | # or in config/master.key. This key is used to decrypt credentials (and other encrypted files).
21 | # config.require_master_key = true
22 |
23 | # Disable serving static files from the `/public` folder by default since
24 | # Apache or NGINX already handles this.
25 | config.public_file_server.enabled = ENV["RAILS_SERVE_STATIC_FILES"].present?
26 |
27 | # Compress CSS using a preprocessor.
28 | # config.assets.css_compressor = :sass
29 |
30 | # Do not fallback to assets pipeline if a precompiled asset is missed.
31 | config.assets.compile = false
32 |
33 | # Enable serving of images, stylesheets, and JavaScripts from an asset server.
34 | # config.asset_host = "http://assets.example.com"
35 |
36 | # Specifies the header that your server uses for sending files.
37 | # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for Apache
38 | # config.action_dispatch.x_sendfile_header = "X-Accel-Redirect" # for NGINX
39 |
40 | # Store uploaded files on the local file system (see config/storage.yml for options).
41 | config.active_storage.service = :local
42 |
43 | # Mount Action Cable outside main process or domain.
44 | # config.action_cable.mount_path = nil
45 | # config.action_cable.url = "wss://example.com/cable"
46 | # config.action_cable.allowed_request_origins = [ "http://example.com", /http:\/\/example.*/ ]
47 |
48 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
49 | # config.force_ssl = true
50 |
51 | # Include generic and useful information about system operation, but avoid logging too much
52 | # information to avoid inadvertent exposure of personally identifiable information (PII).
53 | config.log_level = :info
54 |
55 | # Prepend all log lines with the following tags.
56 | config.log_tags = [ :request_id ]
57 |
58 | # Use a different cache store in production.
59 | # config.cache_store = :mem_cache_store
60 |
61 | # Use a real queuing backend for Active Job (and separate queues per environment).
62 | # config.active_job.queue_adapter = :resque
63 | # config.active_job.queue_name_prefix = "tdnm_production"
64 |
65 | config.action_mailer.perform_caching = false
66 |
67 | # Ignore bad email addresses and do not raise email delivery errors.
68 | # Set this to true and configure the email server for immediate delivery to raise delivery errors.
69 | # config.action_mailer.raise_delivery_errors = false
70 |
71 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
72 | # the I18n.default_locale when a translation cannot be found).
73 | config.i18n.fallbacks = true
74 |
75 | # Don't log any deprecations.
76 | config.active_support.report_deprecations = false
77 |
78 | # Use default logging formatter so that PID and timestamp are not suppressed.
79 | config.log_formatter = ::Logger::Formatter.new
80 |
81 | # Use a different logger for distributed setups.
82 | # require "syslog/logger"
83 | # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new "app-name")
84 |
85 | if ENV["RAILS_LOG_TO_STDOUT"].present?
86 | logger = ActiveSupport::Logger.new(STDOUT)
87 | logger.formatter = config.log_formatter
88 | config.logger = ActiveSupport::TaggedLogging.new(logger)
89 | end
90 |
91 | # Do not dump schema after migrations.
92 | config.active_record.dump_schema_after_migration = false
93 |
94 | # Inserts middleware to perform automatic connection switching.
95 | # The `database_selector` hash is used to pass options to the DatabaseSelector
96 | # middleware. The `delay` is used to determine how long to wait after a write
97 | # to send a subsequent read to the primary.
98 | #
99 | # The `database_resolver` class is used by the middleware to determine which
100 | # database is appropriate to use based on the time delay.
101 | #
102 | # The `database_resolver_context` class is used by the middleware to set
103 | # timestamps for the last write to the primary. The resolver uses the context
104 | # class timestamps to determine how long to wait before reading from the
105 | # replica.
106 | #
107 | # By default Rails will store a last write timestamp in the session. The
108 | # DatabaseSelector middleware is designed as such you can define your own
109 | # strategy for connection switching and pass that into the middleware through
110 | # these configuration options.
111 | # config.active_record.database_selector = { delay: 2.seconds }
112 | # config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver
113 | # config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session
114 |
115 | # lograge
116 | config.lograge.enabled = true
117 | config.lograge.formatter = Lograge::Formatters::Raw.new
118 |
119 | # Stackdriver Shared parameters
120 | config.google_cloud.project_id = ENV['GOOGLE_CLOUD_PROJECT_ID']
121 | config.google_cloud.keyfile = ENV['GOOGLE_CLOUD_KEYFILE_PATH']
122 | config.google_cloud.logging.log_name = 'tdnm_app'
123 | end
124 |
--------------------------------------------------------------------------------
/config/environments/test.rb:
--------------------------------------------------------------------------------
1 | require "active_support/core_ext/integer/time"
2 |
3 | # The test environment is used exclusively to run your application's
4 | # test suite. You never need to work with it otherwise. Remember that
5 | # your test database is "scratch space" for the test suite and is wiped
6 | # and recreated between test runs. Don't rely on the data there!
7 |
8 | Rails.application.configure do
9 | # Settings specified here will take precedence over those in config/application.rb.
10 |
11 | # Turn false under Spring and add config.action_view.cache_template_loading = true
12 | config.cache_classes = true
13 |
14 | # Do not eager load code on boot. This avoids loading your whole application
15 | # just for the purpose of running a single test. If you are using a tool that
16 | # preloads Rails for running tests, you may have to set it to true.
17 | config.eager_load = false
18 |
19 | # Configure public file server for tests with Cache-Control for performance.
20 | config.public_file_server.enabled = true
21 | config.public_file_server.headers = {
22 | "Cache-Control" => "public, max-age=#{1.hour.to_i}"
23 | }
24 |
25 | # Show full error reports and disable caching.
26 | config.consider_all_requests_local = true
27 | config.action_controller.perform_caching = false
28 | config.cache_store = :null_store
29 |
30 | # Raise exceptions instead of rendering exception templates.
31 | config.action_dispatch.show_exceptions = false
32 |
33 | # Disable request forgery protection in test environment.
34 | config.action_controller.allow_forgery_protection = false
35 |
36 | # Store uploaded files on the local file system in a temporary directory.
37 | config.active_storage.service = :test
38 |
39 | config.action_mailer.perform_caching = false
40 |
41 | # Tell Action Mailer not to deliver emails to the real world.
42 | # The :test delivery method accumulates sent emails in the
43 | # ActionMailer::Base.deliveries array.
44 | config.action_mailer.delivery_method = :test
45 |
46 | # Print deprecation notices to the stderr.
47 | config.active_support.deprecation = :stderr
48 |
49 | # Raise exceptions for disallowed deprecations.
50 | config.active_support.disallowed_deprecation = :raise
51 |
52 | # Tell Active Support which deprecation messages to disallow.
53 | config.active_support.disallowed_deprecation_warnings = []
54 |
55 | # Raises error for missing translations.
56 | # config.i18n.raise_on_missing_translations = true
57 |
58 | # Annotate rendered view with file names.
59 | # config.action_view.annotate_rendered_view_with_filenames = true
60 | end
61 |
--------------------------------------------------------------------------------
/config/initializers/application_controller_renderer.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # ActiveSupport::Reloader.to_prepare do
4 | # ApplicationController.renderer.defaults.merge!(
5 | # http_host: 'example.org',
6 | # https: false
7 | # )
8 | # end
9 |
--------------------------------------------------------------------------------
/config/initializers/assets.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Version of your assets, change this if you want to expire all your assets.
4 | Rails.application.config.assets.version = "1.0"
5 |
6 | # Add additional assets to the asset load path.
7 | # Rails.application.config.assets.paths << Emoji.images_path
8 |
9 | # Precompile additional assets.
10 | # application.js, application.css, and all non-JS/CSS in the app/assets
11 | # folder are already added.
12 | # Rails.application.config.assets.precompile += %w( admin.js admin.css )
13 |
14 | # NOTE: avoid segmentation fault
15 | # https://github.com/sass/sassc-ruby/issues/207
16 | # https://github.com/rails/sprockets/issues/640
17 | Sprockets.export_concurrent = false
18 |
--------------------------------------------------------------------------------
/config/initializers/avo.rb:
--------------------------------------------------------------------------------
1 | # For more information regaring these settings check out our docs https://docs.avohq.io
2 | Avo.configure do |config|
3 | ## == Routing ==
4 | config.root_path = '/avo'
5 |
6 | # Where should the user be redirected when he hits the `/avo` url
7 | # config.home_path = nil
8 |
9 | ## == Licensing ==
10 | config.license = 'community' # change this to 'pro' when you add the license key
11 | # config.license_key = ENV['AVO_LICENSE_KEY']
12 |
13 | ## == Set the context ==
14 | config.set_context do
15 | # Return a context object that gets evaluated in Avo::ApplicationController
16 | end
17 |
18 | ## == Authentication ==
19 | # config.current_user_method = {}
20 | # config.authenticate_with = {}
21 | config.current_user_method do
22 | if session[:user_id] == "eip155:1:#{Rails.application.credentials.admin_user_wallet_id}"
23 | @current_user = session[:user_id]
24 | else
25 | flash[:notice] = "Hello '#{session[:user_id]}' !!!"
26 | redirect_to '/signin'
27 | end
28 | end
29 |
30 | ## == Authorization ==
31 | # config.authorization_methods = {
32 | # index: 'index?',
33 | # show: 'show?',
34 | # edit: 'edit?',
35 | # new: 'new?',
36 | # update: 'update?',
37 | # create: 'create?',
38 | # destroy: 'destroy?',
39 | # }
40 | # config.raise_error_on_missing_policy = false
41 |
42 | ## == Localization ==
43 | # config.locale = 'en-US'
44 |
45 | ## == Customization ==
46 | # config.app_name = 'Avocadelicious'
47 | # config.timezone = 'UTC'
48 | # config.currency = 'USD'
49 | # config.per_page = 24
50 | # config.per_page_steps = [12, 24, 48, 72]
51 | # config.via_per_page = 8
52 | # config.default_view_type = :table
53 | # config.hide_layout_when_printing = false
54 | # config.id_links_to_resource = false
55 | # config.full_width_container = false
56 | # config.full_width_index_view = false
57 | # config.cache_resources_on_index_view = true
58 | # config.search_debounce = 300
59 | # config.view_component_path = "app/components"
60 | # config.display_license_request_timeout_error = true
61 | # config.disabled_features = []
62 |
63 |
64 | ## == Breadcrumbs ==
65 | # config.display_breadcrumbs = true
66 | # config.set_initial_breadcrumbs do
67 | # add_breadcrumb "Home", '/avo'
68 | # end
69 |
70 | ## == Menus ==
71 | # config.main_menu = -> {
72 | # section "Dashboards", icon: "dashboards" do
73 | # all_dashboards
74 | # end
75 |
76 | # section "Resources", icon: "resources" do
77 | # all_resources
78 | # end
79 |
80 | # section "Tools", icon: "tools" do
81 | # all_tools
82 | # end
83 | # }
84 | # config.profile_menu = -> {
85 | # link "Profile", path: "/avo/profile", icon: "user-circle"
86 | # }
87 | end
88 |
--------------------------------------------------------------------------------
/config/initializers/backtrace_silencers.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
4 | # Rails.backtrace_cleaner.add_silencer { |line| /my_noisy_library/.match?(line) }
5 |
6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code
7 | # by setting BACKTRACE=1 before calling your invocation, like "BACKTRACE=1 ./bin/rails runner 'MyClass.perform'".
8 | Rails.backtrace_cleaner.remove_silencers! if ENV["BACKTRACE"]
9 |
--------------------------------------------------------------------------------
/config/initializers/content_security_policy.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Define an application-wide content security policy.
4 | # See the Securing Rails Applications Guide for more information:
5 | # https://guides.rubyonrails.org/security.html#content-security-policy-header
6 |
7 | # Rails.application.configure do
8 | # config.content_security_policy do |policy|
9 | # policy.default_src :self, :https
10 | # policy.font_src :self, :https, :data
11 | # policy.img_src :self, :https, :data
12 | # policy.object_src :none
13 | # policy.script_src :self, :https
14 | # policy.style_src :self, :https
15 | # # Specify URI for violation reports
16 | # # policy.report_uri "/csp-violation-report-endpoint"
17 | # end
18 | #
19 | # # Generate session nonces for permitted importmap and inline scripts
20 | # config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s }
21 | # config.content_security_policy_nonce_directives = %w(script-src)
22 | #
23 | # # Report violations without enforcing the policy.
24 | # # config.content_security_policy_report_only = true
25 | # end
26 |
--------------------------------------------------------------------------------
/config/initializers/cookies_serializer.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Specify a serializer for the signed and encrypted cookie jars.
4 | # Valid options are :json, :marshal, and :hybrid.
5 | Rails.application.config.action_dispatch.cookies_serializer = :json
6 |
--------------------------------------------------------------------------------
/config/initializers/filter_parameter_logging.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Configure sensitive parameters which will be filtered from the log file.
4 | Rails.application.config.filter_parameters += [
5 | :passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn
6 | ]
7 |
--------------------------------------------------------------------------------
/config/initializers/inflections.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new inflection rules using the following format. Inflections
4 | # are locale specific, and you may define rules for as many different
5 | # locales as you wish. All of these examples are active by default:
6 | # ActiveSupport::Inflector.inflections(:en) do |inflect|
7 | # inflect.plural /^(ox)$/i, "\\1en"
8 | # inflect.singular /^(ox)en/i, "\\1"
9 | # inflect.irregular "person", "people"
10 | # inflect.uncountable %w( fish sheep )
11 | # end
12 |
13 | # These inflection rules are supported but not enabled by default:
14 | # ActiveSupport::Inflector.inflections(:en) do |inflect|
15 | # inflect.acronym "RESTful"
16 | # end
17 |
--------------------------------------------------------------------------------
/config/initializers/meta_tags.rb:
--------------------------------------------------------------------------------
1 | MetaTags.configure do |c|
2 | c.title_limit = 70
3 | c.description_limit = 160
4 | c.keywords_limit = 255
5 | c.keywords_separator = ', '
6 | end
7 |
--------------------------------------------------------------------------------
/config/initializers/mime_types.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new mime types for use in respond_to blocks:
4 | # Mime::Type.register "text/richtext", :rtf
5 |
--------------------------------------------------------------------------------
/config/initializers/omniauth.rb:
--------------------------------------------------------------------------------
1 | Rails.application.config.middleware.use OmniAuth::Builder do
2 | unless Rails.env.test?
3 | issuer = 'https://oidc.login.xyz/'
4 | client_options = {
5 | scheme: 'https',
6 | host: 'oidc.login.xyz',
7 | port: 443,
8 | authorization_endpoint: '/authorize',
9 | token_endpoint: '/token',
10 | userinfo_endpoint: '/userinfo',
11 | jwks_uri: 'https://oidc.login.xyz/jwk',
12 | identifier: Rails.application.credentials.dig(Rails.env.to_sym, :siwe_client_id),
13 | secret: Rails.application.credentials.dig(Rails.env.to_sym, :siwe_client_secret)
14 | }
15 |
16 | provider :siwe, issuer: issuer, client_options: client_options
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/config/initializers/permissions_policy.rb:
--------------------------------------------------------------------------------
1 | # Define an application-wide HTTP permissions policy. For further
2 | # information see https://developers.google.com/web/updates/2018/06/feature-policy
3 | #
4 | # Rails.application.config.permissions_policy do |f|
5 | # f.camera :none
6 | # f.gyroscope :none
7 | # f.microphone :none
8 | # f.usb :none
9 | # f.fullscreen :self
10 | # f.payment :self, "https://secure.example.com"
11 | # end
12 |
--------------------------------------------------------------------------------
/config/initializers/session_store.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | Rails.application.config.session_store :cookie_store, key: '_tdnm_session'
4 |
--------------------------------------------------------------------------------
/config/initializers/wrap_parameters.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # This file contains settings for ActionController::ParamsWrapper which
4 | # is enabled by default.
5 |
6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
7 | ActiveSupport.on_load(:action_controller) do
8 | wrap_parameters format: [:json]
9 | end
10 |
11 | # To enable root element in JSON for ActiveRecord objects.
12 | # ActiveSupport.on_load(:active_record) do
13 | # self.include_root_in_json = true
14 | # end
15 |
--------------------------------------------------------------------------------
/config/locales/avo.en.yml:
--------------------------------------------------------------------------------
1 | en:
2 | avo:
3 | dashboard: 'Dashboard'
4 | dashboards: 'Dashboards'
5 | choose_a_country: 'Choose a country'
6 | choose_an_option: 'Choose an option'
7 | are_you_sure_you_want_to_run_this_option: 'Are you sure you want to run this action?'
8 | are_you_sure_detach_item: 'Are you sure you want to detach this %{item}.'
9 | run: 'Run'
10 | cancel: 'Cancel'
11 | action_ran_successfully: 'Action ran successfully!'
12 | details: "details"
13 | unauthorized: 'Unauthorized'
14 | attachment_class_attached: '%{attachment_class} attached.'
15 | attachment_class_detached: '%{attachment_class} detached.'
16 | resource_updated: 'Resource updated'
17 | resource_created: 'Resource created'
18 | resource_destroyed: 'Resource destroyed'
19 | switch_to_view: "Switch to %{view_type} view"
20 | click_to_reveal_filters: "Click to reveal filters"
21 | attachment_destroyed: 'Attachment destroyed'
22 | failed_to_find_attachment: 'Failed to find attachment'
23 | you_missed_something_check_form: 'You might have missed something. Please check the form.'
24 | remove_selection: 'Remove selection'
25 | select_item: 'Select item'
26 | select_all: 'Select all on page'
27 | delete_file: 'Delete file'
28 | delete: 'delete'
29 | delete_item: 'Delete %{item}'
30 | download_item: 'Download %{item}'
31 | download_file: 'Download file'
32 | download: 'Download'
33 | view: 'View'
34 | view_item: 'view %{item}'
35 | edit: 'edit'
36 | edit_item: 'edit %{item}'
37 | detach_item: 'detach %{item}'
38 | number_of_items:
39 | zero: 'no %{item}'
40 | one: 'one %{item}'
41 | other: '%{count} %{item}'
42 | are_you_sure: 'Are you sure?'
43 | filters: 'Filters'
44 | per_page: 'Per page'
45 | more: 'More'
46 | attach: 'Attach'
47 | cancel: 'Cancel'
48 | save: 'Save'
49 | attach_and_attach_another: 'Attach & Attach another'
50 | hide_content: 'Hide content'
51 | show_content: 'Show content'
52 | no_related_item_found: 'No related %{item} found'
53 | no_item_found: 'No %{item} found'
54 | loading: 'Loading'
55 | confirm: 'Confirm'
56 | actions: 'Actions'
57 | resources: 'Resources'
58 | oops_nothing_found: 'Oops! Nothing found...'
59 | type_to_search: 'Type to search.'
60 | and_x_other_resources: 'and %{count} other resources'
61 | go_back: 'Go back'
62 | home: 'Home'
63 | new: 'new'
64 | attach_item: 'Attach %{item}'
65 | choose_item: 'Choose %{item}'
66 | create_new_item: 'Create new %{item}'
67 | table_view: 'Table view'
68 | grid_view: 'Grid view'
69 | next_page: 'Next page'
70 | prev_page: 'Previous page'
71 | list_is_empty: 'List is empty'
72 | field_translations:
73 | file:
74 | zero: 'files'
75 | one: 'file'
76 | other: 'files'
77 | people:
78 | zero: 'peeps'
79 | one: 'peep'
80 | other: 'peeps'
81 | resource_translations:
82 | user:
83 | zero: 'users'
84 | one: 'user'
85 | other: 'users'
86 | reset_filters: 'Reset filters'
87 | not_authorized: 'You are not authorized to perform this action.'
88 | search:
89 | placeholder: 'Search'
90 | cancel_button: 'Cancel'
91 | sign_out: 'Sign out'
92 | failed: 'Failed'
93 | failed_to_load: 'Failed to load'
94 | key_value_field:
95 | key: 'Key'
96 | value: 'Value'
97 | add_row: 'Add row'
98 | delete_row: 'Delete row'
99 | was_successfully_created: 'was successfully created'
100 | was_successfully_updated: 'was successfully updated'
101 | clear_value: "Clear value"
102 | tools: Tools
103 | order:
104 | reorder_record: Reorder record
105 | higher: Move record higher
106 | lower: Move record lower
107 | to_top: Move record to top
108 | to_bottom: Move record to bottom
109 | empty_dashboard_message: Add cards to this dashboard
110 | no_cards_present: No cards present
111 | no_options_available: No options available
112 |
--------------------------------------------------------------------------------
/config/locales/en.yml:
--------------------------------------------------------------------------------
1 | # Files in the config/locales directory are used for internationalization
2 | # and are automatically loaded by Rails. If you want to use locales other
3 | # than English, add the necessary files in this directory.
4 | #
5 | # To use the locales, use `I18n.t`:
6 | #
7 | # I18n.t 'hello'
8 | #
9 | # In views, this is aliased to just `t`:
10 | #
11 | # <%= t('hello') %>
12 | #
13 | # To use a different locale, set it with `I18n.locale`:
14 | #
15 | # I18n.locale = :es
16 | #
17 | # This would use the information in config/locales/es.yml.
18 | #
19 | # The following keys must be escaped otherwise they will not be retrieved by
20 | # the default I18n backend:
21 | #
22 | # true, false, on, off, yes, no
23 | #
24 | # Instead, surround them with single quotes.
25 | #
26 | # en:
27 | # 'true': 'foo'
28 | #
29 | # To learn more, please read the Rails Internationalization guide
30 | # available at https://guides.rubyonrails.org/i18n.html.
31 |
32 | en:
33 | hello: "Hello world"
34 |
--------------------------------------------------------------------------------
/config/puma.rb:
--------------------------------------------------------------------------------
1 | # Puma can serve each request in a thread from an internal thread pool.
2 | # The `threads` method setting takes two numbers: a minimum and maximum.
3 | # Any libraries that use thread pools should be configured to match
4 | # the maximum value specified for Puma. Default is set to 5 threads for minimum
5 | # and maximum; this matches the default thread size of Active Record.
6 | #
7 | max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
8 | min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count }
9 | threads min_threads_count, max_threads_count
10 |
11 | # Specifies the `worker_timeout` threshold that Puma will use to wait before
12 | # terminating a worker in development environments.
13 | #
14 | worker_timeout 3600 if ENV.fetch("RAILS_ENV", "development") == "development"
15 |
16 | # Specifies the `port` that Puma will listen on to receive requests; default is 3000.
17 | #
18 | port ENV.fetch("PORT") { 3000 }
19 |
20 | # Specifies the `environment` that Puma will run in.
21 | #
22 | environment ENV.fetch("RAILS_ENV") { "development" }
23 |
24 | # Specifies the `pidfile` that Puma will use.
25 | pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }
26 |
27 | # Specifies the number of `workers` to boot in clustered mode.
28 | # Workers are forked web server processes. If using threads and workers together
29 | # the concurrency of the application would be max `threads` * `workers`.
30 | # Workers do not work on JRuby or Windows (both of which do not support
31 | # processes).
32 | #
33 | # workers ENV.fetch("WEB_CONCURRENCY") { 2 }
34 |
35 | # Use the `preload_app!` method when specifying a `workers` number.
36 | # This directive tells Puma to first boot the application and load code
37 | # before forking the application. This takes advantage of Copy On Write
38 | # process behavior so workers use less memory.
39 | #
40 | # preload_app!
41 |
42 | # Allow puma to be restarted by `rails restart` command.
43 | plugin :tmp_restart
44 |
--------------------------------------------------------------------------------
/config/routes.rb:
--------------------------------------------------------------------------------
1 | Rails.application.routes.draw do
2 | mount Avo::Engine, at: Avo.configuration.root_path
3 | if Rails.env.development?
4 | mount GraphiQL::Rails::Engine, at: "/graphiql", graphql_path: "/graphql"
5 | end
6 | post "/graphql", to: "graphql#execute"
7 |
8 | root 'articles#index'
9 |
10 | get '/atom.xml', controller: 'articles', action: 'index', format: 'atom'
11 | get '/:year/:month/:day/:slug', to: 'articles#show', year: /\d{4}/, month: /\d{2}/, day: /\d{2}/
12 | get '/blog/:year/:month/:day/:slug', to: redirect('/%{year}/%{month}/%{day}/%{slug}')
13 |
14 | get '/signin', to: 'sessions#new'
15 | get '/auth/:provider/callback', to: 'sessions#create'
16 |
17 | get '/:title', to: 'articles#show', as: :article
18 | end
19 |
--------------------------------------------------------------------------------
/config/sitemap.rb:
--------------------------------------------------------------------------------
1 | SitemapGenerator::Sitemap.default_host = ENV['DEFAULT_HOST'] || "http://www.example.com"
2 |
3 | SitemapGenerator::Sitemap.create do
4 | Article.published.find_each do |a|
5 | d = a.published_on
6 | add(
7 | article_path(title: a.title),
8 | lastmod: a.updated_at
9 | )
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/config/spring.rb:
--------------------------------------------------------------------------------
1 | %w[
2 | .ruby-version
3 | .rbenv-vars
4 | tmp/restart.txt
5 | tmp/caching-dev.txt
6 | ].each { |path| Spring.watch(path) }
7 |
--------------------------------------------------------------------------------
/config/storage.yml:
--------------------------------------------------------------------------------
1 | test:
2 | service: Disk
3 | root: <%= Rails.root.join("tmp/storage") %>
4 |
5 | local:
6 | service: Disk
7 | root: <%= Rails.root.join("storage") %>
8 |
9 | # Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key)
10 | # amazon:
11 | # service: S3
12 | # access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
13 | # secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
14 | # region: us-east-1
15 | # bucket: your_own_bucket
16 |
17 | # Remember not to checkin your GCS keyfile to a repository
18 | # google:
19 | # service: GCS
20 | # project: your_project
21 | # credentials: <%= Rails.root.join("path/to/gcs.keyfile") %>
22 | # bucket: your_own_bucket
23 |
24 | # Use rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key)
25 | # microsoft:
26 | # service: AzureStorage
27 | # storage_account_name: your_account_name
28 | # storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %>
29 | # container: your_container_name
30 |
31 | # mirror:
32 | # service: Mirror
33 | # primary: local
34 | # mirrors: [ amazon, google, microsoft ]
35 |
--------------------------------------------------------------------------------
/db/migrate/20150803141807_create_articles.rb:
--------------------------------------------------------------------------------
1 | class CreateArticles < ActiveRecord::Migration[5.1]
2 | def change
3 | create_table :articles do |t|
4 | t.string :title, null: false
5 | t.string :body, null: false
6 | t.string :url_title, null: false
7 | t.date :published_on
8 | t.timestamps null: false
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/db/migrate/20150804044739_create_weblogs.rb:
--------------------------------------------------------------------------------
1 | class CreateWeblogs < ActiveRecord::Migration[5.1]
2 | def change
3 | create_table :weblogs do |t|
4 | t.string :title, null: false
5 |
6 | t.timestamps null: false
7 | end
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/db/migrate/20160110151755_change_column_article_body_to_text.rb:
--------------------------------------------------------------------------------
1 | class ChangeColumnArticleBodyToText < ActiveRecord::Migration[5.1]
2 | def change
3 | change_column :articles, :body, :text
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20161023132949_add_draft_to_articles.rb:
--------------------------------------------------------------------------------
1 | class AddDraftToArticles < ActiveRecord::Migration[5.1]
2 | def change
3 | add_column :articles, :draft, :boolean, null: false, default: false
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20180326163716_add_default_eye_catching_image_url_to_weblog.rb:
--------------------------------------------------------------------------------
1 | class AddDefaultEyeCatchingImageUrlToWeblog < ActiveRecord::Migration[5.1]
2 | def change
3 | add_column :weblogs, :default_eye_catching_image_url, :string
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20180416143233_rename_url_title_to_slug_on_articles.rb:
--------------------------------------------------------------------------------
1 | class RenameUrlTitleToSlugOnArticles < ActiveRecord::Migration[5.1]
2 | def change
3 | rename_column :articles, :url_title, :slug
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20180416150121_add_eye_catching_image_url_to_articles.rb:
--------------------------------------------------------------------------------
1 | class AddEyeCatchingImageUrlToArticles < ActiveRecord::Migration[5.1]
2 | def change
3 | add_column :articles, :eye_catching_image_url, :string, null: false, default: ''
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20190604125626_change_articles_eyecatching_url_size.rb:
--------------------------------------------------------------------------------
1 | class ChangeArticlesEyecatchingUrlSize < ActiveRecord::Migration[5.2]
2 | def change
3 | change_column :articles, :eye_catching_image_url, :string, limit: 1024
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20190924161405_add_foreign_key_constraint_to_active_storage_attachments_for_blob_id.active_storage.rb:
--------------------------------------------------------------------------------
1 | # This migration comes from active_storage (originally 20180723000244)
2 | class AddForeignKeyConstraintToActiveStorageAttachmentsForBlobId < ActiveRecord::Migration[6.0]
3 | def up
4 | return if foreign_key_exists?(:active_storage_attachments, column: :blob_id)
5 |
6 | if table_exists?(:active_storage_blobs)
7 | add_foreign_key :active_storage_attachments, :active_storage_blobs, column: :blob_id
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/db/migrate/20200324153331_add_index_to_articles_published_on.rb:
--------------------------------------------------------------------------------
1 | class AddIndexToArticlesPublishedOn < ActiveRecord::Migration[6.0]
2 | def change
3 | add_index :articles, :published_on, name: :idx_published_on
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20210908153117_add_unique_index_to_article_title.rb:
--------------------------------------------------------------------------------
1 | class AddUniqueIndexToArticleTitle < ActiveRecord::Migration[6.1]
2 | def change
3 | add_index :articles, :title, unique: true
4 | end
5 | end
6 |
7 |
--------------------------------------------------------------------------------
/db/migrate/20230303004038_rename_column_eye_catching_image_url_to_featured_imaeg_url.rb:
--------------------------------------------------------------------------------
1 | class RenameColumnEyeCatchingImageUrlToFeaturedImaegUrl < ActiveRecord::Migration[7.0]
2 | def change
3 | rename_column :articles, :eye_catching_image_url, :featured_image_url
4 | rename_column :weblogs, :default_eye_catching_image_url, :default_featured_image_url
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/db/schema.rb:
--------------------------------------------------------------------------------
1 | # This file is auto-generated from the current state of the database. Instead
2 | # of editing this file, please use the migrations feature of Active Record to
3 | # incrementally modify your database, and then regenerate this schema definition.
4 | #
5 | # This file is the source Rails uses to define your schema when running `bin/rails
6 | # db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
7 | # be faster and is potentially less error prone than running all of your
8 | # migrations from scratch. Old migrations may fail to apply correctly if those
9 | # migrations use external dependencies or application code.
10 | #
11 | # It's strongly recommended that you check this file into your version control system.
12 |
13 | ActiveRecord::Schema[7.0].define(version: 2023_03_03_004038) do
14 | # These are extensions that must be enabled in order to support this database
15 | enable_extension "plpgsql"
16 |
17 | create_table "articles", force: :cascade do |t|
18 | t.string "title", null: false
19 | t.text "body", null: false
20 | t.string "slug", null: false
21 | t.date "published_on"
22 | t.datetime "created_at", null: false
23 | t.datetime "updated_at", null: false
24 | t.boolean "draft", default: false, null: false
25 | t.string "featured_image_url", limit: 1024, default: "", null: false
26 | t.index ["published_on"], name: "idx_published_on"
27 | t.index ["title"], name: "index_articles_on_title", unique: true
28 | end
29 |
30 | create_table "weblogs", force: :cascade do |t|
31 | t.string "title", null: false
32 | t.datetime "created_at", null: false
33 | t.datetime "updated_at", null: false
34 | t.string "default_featured_image_url"
35 | end
36 |
37 | end
38 |
--------------------------------------------------------------------------------
/db/seeds.rb:
--------------------------------------------------------------------------------
1 | # This file should contain all the record creation needed to seed the database with its default values.
2 | # The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup).
3 | #
4 | # Examples:
5 | #
6 | # movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }])
7 | # Character.create(name: 'Luke', movie: movies.first)
8 |
9 | ApplicationRecord.transaction do
10 |
11 | weblog = Weblog.create!(title: 'My Weblog')
12 |
13 | Article.create!(
14 | title: 'My First Article',
15 | published_on: Date.today,
16 | slug: '01',
17 | body: <<~EOS,
18 | # Hello tdnm
19 |
20 | I'm fine!
21 | EOS
22 | )
23 | end
24 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: "3"
2 |
3 | services:
4 | https-portal:
5 | image: steveltn/https-portal:1
6 | ports:
7 | - '80:80'
8 | - '443:443'
9 | depends_on:
10 | - webapp
11 | environment:
12 | DOMAINS: 'tdnm.localhost -> http://webapp:3000'
13 | STAGE: 'local'
14 |
15 | webapp:
16 | build:
17 | context: .
18 | dockerfile: Dockerfile
19 | links:
20 | - db
21 | environment:
22 | - DATABASE_HOST=db
23 | - DATABASE_PASSWORD=postgres
24 | - DEFAULT_URL=https://tdnm.localhost
25 | - SELENIUM_HOST=selenium
26 | - SELENIUM_APP_HOST=webapp
27 | - TZ=Asia/Tokyo
28 | volumes:
29 | - .:/app
30 | - bundle_cache:/app/vendor/bundle
31 | command: ["wait-for-it", "db:5432", "--", "bash", "-c", "bin/setup; rm tmp/pids/server.pid 2>/dev/null; bin/rails s -b '0.0.0.0'"]
32 |
33 | db:
34 | image: postgres:14
35 | volumes:
36 | - pg_data:/var/lib/postgresql/data
37 | environment:
38 | - POSTGRES_PASSWORD=postgres
39 |
40 | selenium:
41 | image: selenium/standalone-firefox-debug
42 |
43 | volumes:
44 | pg_data:
45 | bundle_cache:
46 |
--------------------------------------------------------------------------------
/lib/assets/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenchan/tdnm_blog/2aa48ea6eaff17758f5477a8a638671e94275fae/lib/assets/.keep
--------------------------------------------------------------------------------
/lib/tasks/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenchan/tdnm_blog/2aa48ea6eaff17758f5477a8a638671e94275fae/lib/tasks/.keep
--------------------------------------------------------------------------------
/lib/tasks/import.thor:
--------------------------------------------------------------------------------
1 | require 'find'
2 |
3 | class TdnmCli < Thor
4 | desc 'import', 'import from middleman blog'
5 | def import(base_dir)
6 | require './config/environment'
7 |
8 | entries = Find.find("#{base_dir}/source").grep(/\d{4}-\d{2}-\d{2}-*/).map {|e|
9 | a = YAML.load_file(e)
10 | a["body"] = File.read(e).gsub(/---.+---\s+/m, '')
11 | a["url_title"] = e.match(/\d{4}-\d{2}-\d{2}-([^-].+?)\./)[1]
12 | a
13 | }
14 |
15 | Article.transaction do
16 | entries.each do |e|
17 | Article.create!(
18 | title: e["title"],
19 | url_title: e["url_title"],
20 | body: e["body"],
21 | published_on: e["date"]
22 | )
23 | end
24 | end
25 | end
26 | end
27 |
--------------------------------------------------------------------------------
/lib/tasks/rbs.rake:
--------------------------------------------------------------------------------
1 | require 'rbs_rails/rake_task'
2 | RbsRails::RakeTask.new
3 |
--------------------------------------------------------------------------------
/log/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenchan/tdnm_blog/2aa48ea6eaff17758f5477a8a638671e94275fae/log/.keep
--------------------------------------------------------------------------------
/public/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
You may have mistyped the address or the page may have moved.
63 |If you are the application owner check the logs for more information.
65 |Maybe you tried to change something you didn't have access to.
63 |If you are the application owner check the logs for more information.
65 |If you are the application owner check the logs for more information.
64 |