ホーム 記事一覧 ブック DH週間トピックス 検索 このサイトについて
English
Drupal の GitHub Webhook モジュールを改善しました。

Drupal の GitHub Webhook モジュールを改善しました。

Drupal の管理画面から GitHub Actions をトリガーするカスタムモジュール「GitHub Webhook」を改善しました。 https://github.com/nakamura196/Drupal-module-github_webhook 元は複数リポジトリ対応の基本的なモジュールでしたが、UI のタブ分離、権限の細分化、ワークフローステータス表示、自動トリガーなどの機能を追加しています。 改善前のモジュール 元のモジュールは、以下のような構成でした。 ファイル数 : 5ファイル(info.yml、routing.yml、links.menu.yml、permissions.yml、SettingsForm.php) 対応バージョン : Drupal 10 のみ リポジトリ : 複数対応済み(AJAX で動的追加・削除) 画面 : 設定とトリガーが同一画面(アコーディオン2つ) 権限 : access github webhook settings の1権限のみ(設定もトリガーも同じ権限) トークン管理 : パスワードフィールドに #default_value を設定(HTML ソースに平文で出力される) HTTP クライアント : new \GuzzleHttp\Client() を直接インスタンス化 例外クラス : use 文なしで catch ブロックに記述(名前空間の解決が不正) // 改善前: トークンが #default_value に設定されていた $form['settings']['github_token'] = [ '#type' => 'password', '#title' => $this->t('GitHub Token'), '#default_value' => $config->get('github_token'), // HTML に平文出力される ]; // 改善前: Guzzle クライアントを直接 new していた $client = new \GuzzleHttp\Client(); 変更の全体像 改善前後のファイル構成の比較です。* は変更、+ は新規追加を示します。 ...

Drupal 10 の管理画面からモジュール更新とコアアップデートを行う

Drupal 10 の管理画面からモジュール更新とコアアップデートを行う

共用サーバー上の Drupal 10.6.1 で、Backup and Migrate によるバックアップと Automatic Updates によるモジュール・コアの自動更新を設定した手順をまとめる。 現状確認 管理画面の「レポート > サイトの状態」を確認すると、3つの警告が出ていた。 Drupal コアの更新状況:期限切れ(バージョン 10.6.3 が入手可能) PHP APCu available caching:メモリ使用量が75%超え モジュールとテーマの更新状況:期限切れ 「レポート > 利用可能なアップデート」を見ると、以下のモジュールに更新があった。 Consumers 8.x-1.22 Geofield 8.x-1.66 Geofield Map 11.1.1 Leaflet 10.3.11 Backup and Migrate のインストール 更新作業の前に、まずバックアップ手段を用意する。 composer.phar require 'drupal/backup_migrate:^5.1' vendor/bin/drush en backup_migrate vendor/bin/drush cr インストール後、「管理 > 環境設定 > 開発 > バックアップと移動」からクイックバックアップが実行できるようになる。バックアップ元に「デフォルト Drupal データベース」、バックアップ保存先に「ダウンロード」を選択して「今すぐバックアップ」を押すと、データベースのバックアップファイルがダウンロードされる。 Automatic Updates のインストール Automatic Updates モジュールを使うと、管理画面からモジュールやコアのアップデートが行える。 composer.phar require 'drupal/automatic_updates:^3.1' vendor/bin/drush en automatic_updates vendor/bin/drush en automatic_updates_extensions Composer パスの設定 有効化直後、Automatic Updates の画面にエラーが表示された。 ...

さくらレンタルサーバー Drupal 更新手順

さくらレンタルサーバー Drupal 更新手順

さくらのレンタルサーバーでDrupal 10.1.5から10.6.1へアップデートした際の手順をまとめます。 環境 サーバー:さくらのレンタルサーバー Drupal:10.1.5 → 10.6.1 インストール形式:従来型(tarball、web/ディレクトリなし) 事前準備 作業用ディレクトリの作成 バックアップは www 外に保存します(Webからアクセスできないようにするため)。 mkdir -p /home/[ユーザー名]/backups/drupal ファイルのバックアップ cd /home/[ユーザー名]/www tar -czvf /home/[ユーザー名]/backups/drupal/drupal_backup_$(date +%Y%m%d).tar.gz [drupalディレクトリ]/ データベースのバックアップ さくらのレンタルサーバーでは --no-tablespaces オプションが必要です。 cd /home/[ユーザー名]/www/[drupalディレクトリ] ./vendor/bin/drush sql-dump --extra-dump="--no-tablespaces" > /home/[ユーザー名]/backups/drupal/db_backup_$(date +%Y%m%d).sql Drupalコアのアップデート 権限の変更 sites/default ディレクトリは書き込み禁止になっていることが多いため、一時的に変更します。 chmod 755 /home/[ユーザー名]/www/[drupalディレクトリ]/sites/default chmod 644 /home/[ユーザー名]/www/[drupalディレクトリ]/sites/default/default.services.yml Composerでアップデート さくらのレンタルサーバーでは composer コマンドが使えないため、composer.phar を使用します。 cd /home/[ユーザー名]/www/[drupalディレクトリ] php composer.phar require drupal/core-recommended:^10 drupal/core-composer-scaffold:^10 --update-with-dependencies データベース更新とキャッシュクリア ./vendor/bin/drush updatedb -y ./vendor/bin/drush cache:rebuild 権限を戻す chmod 555 /home/[ユーザー名]/www/[drupalディレクトリ]/sites/default chmod 444 /home/[ユーザー名]/www/[drupalディレクトリ]/sites/default/settings.php トラブルシューティング Rulesモジュールの互換性エラー アップデート後に以下のようなエラーが出る場合: ...

Docker環境でDrupal 10にWDBモジュールをセットアップする手順

Docker環境でDrupal 10にWDBモジュールをセットアップする手順

概要 この記事では、Docker環境でDrupal 10を構築し、言語学データベース用のWDBモジュールをインストールする手順を解説します。 前提条件 Docker Desktop がインストールされていること Git がインストールされていること 手順 1. Docker環境の構築 まず、docker-compose.ymlファイルを作成します: services: mariadb: image: mariadb:latest restart: always volumes: - mariadb:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: drupal MYSQL_DATABASE: drupal MYSQL_USER: drupal MYSQL_PASSWORD: drupal drupal: image: drupal:10.2.7-php8.2-apache-bullseye volumes: - ./drupal/files:/opt/drupal/web/sites/default/files - ./drupal/modules:/opt/drupal/web/modules - ./drupal/themes:/opt/drupal/web/themes - ./drupal/private:/opt/drupal/private depends_on: - mariadb ports: - 8080:80 restart: always volumes: mariadb: {} 次に、必要なディレクトリを作成し、コンテナを起動します: ...

DrupalのJSON:APIでcreatedやchangedに対するフィルタを適用する

DrupalのJSON:APIでcreatedやchangedに対するフィルタを適用する

概要 DrupalのJSON:APIでcreatedやchangedに対するフィルタを適用する方法の備忘録です。 背景 以下を参考にしました。 https://www.drupal.org/docs/core-modules-and-themes/core-modules/jsonapi-module/filtering 例えば、6/2以降に更新されたものだけをフィルタリングしようとした際、以下のクエリでは適切に動作しませんでした。 ?filter[a-label][condition][path]=changed&filter[a-label][condition][operator]=%3E%3D&filter[a-label][condition][value]=2025-06-02 正しい方法 以下の記事が参考になりました。 https://www.reddit.com/r/drupal/comments/1bdvu61/json_api_drupal_filter_on_date/ Note that timestamp fields (like created or changed) currently must use a timestamp for filtering: タイムスタンプフィールド(createdやchangedなど)は現在、フィルタリングにタイムスタンプを使用する必要があります。 例えば、2025/6/2のタイムスタンプ1748790000を用いて、以下のようなクエリを使用することで、正しくフィルタリングできました。 ?filter[a-label][condition][path]=changed&filter[a-label][condition][operator]=%3E%3D&filter[a-label][condition][value]=1748790000 まとめ DrupalのJSON:APIで、createdやchangedに対するフィルタを適用する際にお役に立てば幸いです。

IIIF Presentation API v2のIIIFコレクションで、ページネーションを使う

IIIF Presentation API v2のIIIFコレクションで、ページネーションを使う

概要 IIIF Presentation API v2のIIIFコレクションで、ページネーションを使う機会がありましたので、備忘録です。 背景 IIIFコレクションでは、以下のように、複数のマニフェストファイル(およびコレクション)の一覧を提供することができます。 https://iiif.io/api/presentation/2.1/#collection { "@context": "http://iiif.io/api/presentation/2/context.json", "@id": "http://example.org/iiif/collection/top", "@type": "sc:Collection", "label": "Top Level Collection for Example Organization", "viewingHint": "top", "description": "Description of Collection", "attribution": "Provided by Example Organization", "manifests": [ { "@id": "http://example.org/iiif/book1/manifest", "@type": "sc:Manifest", "label": "Book 1" } ] } この時、対象とするマニフェストファイルが多数になった場合、一つのIIIFコレクションでは配信が難しくなりました。 これに対して、以下でページネーションに関する仕様がありましたので、こちらを使ってみます。 https://iiif.io/api/presentation/2.1/#paging ページネーション 上記のページでは、以下のような例が紹介されていました。 { "@context": "http://iiif.io/api/presentation/2/context.json", "@id": "http://example.org/iiif/collection/top", "@type": "sc:Collection", "label": "Example Big Collection", "total": 9316290, "first": "http://example.org/iiif/collection/c1" } { "@context": "http://iiif.io/api/presentation/2/context.json", "@id": "http://example.org/iiif/collection/c1", "@type": "sc:Collection", "within": "http://example.org/iiif/collection/top", "startIndex": 0, "next": "http://example.org/iiif/collection/c2", "manifests": [ // Manifests live here ... ] } まず、一つの目のJSONでコレクション全体のマニフェストファイル数totalを示し、さらにはじめの部分マニフェストファイル群へのリンクをfirstで提示します。 ...

Drupalで管理者以外のユーザーにも設定画面へのアクセスを許可する方法

Drupalで管理者以外のユーザーにも設定画面へのアクセスを許可する方法

本記事の一部はAIが作成しました。 概要 Drupalでカスタムモジュールの設定画面を作成する際、管理者以外のユーザーにもアクセスを許可したい場合があります。今回は、GitHub Webhookモジュールを例に、この問題の解決方法を説明します。 問題の発生 最初の状態では、以下のようなルーティング設定でした: # github_webhook.routing.yml github_webhook.settings: path: '/admin/config/github_webhook' defaults: _form: '\Drupal\github_webhook\Form\SettingsForm' _title: 'GitHub Webhook Settings' requirements: _permission: 'administer site configuration' この設定では、administer site configuration権限を持つ管理者のみがアクセス可能で、一般ユーザーはアクセスできませんでした。 解決方法1: 専用権限の作成 まず、専用の権限を作成します。github_webhook.permissions.ymlファイルを新規作成: access github webhook settings: title: 'Access GitHub Webhook Settings' description: 'Allow users to access GitHub webhook configuration.' そして、ルーティングファイルを更新: # github_webhook.routing.yml github_webhook.settings: path: '/admin/config/github_webhook' defaults: _form: '\Drupal\github_webhook\Form\SettingsForm' _title: 'GitHub Webhook Settings' requirements: _permission: 'access github webhook settings' 問題の発覚: /adminパスの制限 しかし、この変更だけでは解決しませんでした。Drupalでは/admin配下のパスは管理エリアとして扱われ、追加の権限チェックが行われるためです。 ...

DrupalでJSON形式のFieldを扱うための「JSON Field」モジュールを使用する

DrupalでJSON形式のFieldを扱うための「JSON Field」モジュールを使用する

概要 DrupalでJSON形式のFieldを扱うための「JSON Field」モジュールを使用する機会がありましたので、備忘録です。 https://www.drupal.org/project/json_field 結果、以下のようにエディタと共にJSONを扱えるようになりました。 インストール 以下により、ダウンロードします。 composer require 'drupal/json_field:^1.4' drush en json_field さらに、以下により、ウィジェットも有効します。 drush en json_field_widget GUIから有効にする場合には、以下の2つを有効にします。 設定 コンテンツタイプのフィールドの管理において、JSONフィールドを追加します。 そして、「フォームの表示管理」において、ウィジェットを選択します。 結果、コンテンツの編集画面で、以下のようなフォームが表示されます。 まとめ DrupalでJSONを管理するにあたり、参考になりましたら幸いです。

TEI/XMLファイルをS3互換のオブジェクトストレージでホストする

TEI/XMLファイルをS3互換のオブジェクトストレージでホストする

概要 TEI/XMLファイルをS3互換のオブジェクトストレージでホストする機会がありましたので、備忘録です。具体的には、mdx Iのオブジェクトストレージを対象にします。 https://mdx.jp/mdx1/p/about/system 背景 TEI/XMLファイルを読み込み、その内容を可視化するウェブアプリケーション(Next.js)を構築します。この時、ファイル数やサイズが小さい場合は、publicフォルダに格納していましたが、これらが大きくなった場合、別の場所でホストすることを考えました。 場所の選択肢は多々ありますが、今回はS3互換であるmdx Iのオブジェクトストレージを対象にします。 GUIを用いたオブジェクトストレージへのファイルアップロード オブジェクトストレージへTEI/XMLファイルをGUI経由でアップロードする方法も多々あります。その中で、これまではCyberduckを使用する方法や、GakunNin RDMを使用する方法などを紹介しました。 一方、今回の事例では、TEI/XML以外のコンテンツをDrupalで管理していました。そこで、Drupalとオブジェクトストレージを接続し、ユーザはDrupalの操作で完結できるようにしました。 Drupalとオブジェクトストレージの接続 以下のモジュールを使用します。 https://www.drupal.org/project/s3fs インストール後、環境設定のページ/admin/configから、S3 File Systemを選択します。 そして、アクセスキーや秘密鍵を登録し、さらにS3のバケット名を登録します。 またAdvanced Configuration OptionsのCustom Host Settingsにおいて、https://s3ds.mdx.jpを入力します。 これでオブジェクトストレージとの接続設定は完了です。 その後、各コンテンツタイプのフィード設定において、アップロード先として「S3 File System」を選択します。 また、今回はTEI/XMLファイルがアップロード対象となるため、「許可されている拡張子」として、xmlを入力します。 この結果、DrupalのGUIを介してアップロードしたTEI/XMLファイルが、mdx Iのオブジェクトストレージに格納されるようになりました。 (参考)DrupalのJSON:APIを用いたファイルの一括アップロード TEI/XMLの初期登録にあたり、Pythonを用いた一括登録を行いました。JSON:APIを用いたファイルの一括アップロードの方法は、以下の記事などが参考になりました。 https://www.drupal.org/node/3024331 一例ですが、以下のようなスクリプトで実現できました。 import requests import json import os from dotenv import load_dotenv from glob import glob from tqdm import tqdm class ApiClient: def __init__(self): load_dotenv(override=True) # DrupalサイトのURL(例) self.DRUPAL_BASE_URL = os.getenv("DRUPAL_BASE_URL") # エンドポイント(JSON:API) # self.JSONAPI_ENDPOINT = f"{self.DRUPAL_BASE_URL}/jsonapi/node/article" # 認証情報(Basic認証) self.USERNAME = os.getenv("DRUPAL_USERNAME") self.PASSWORD = os.getenv("DRUPAL_PASSWORD") def login(self): # ログインリクエスト login_url = f"{self.DRUPAL_BASE_URL}/user/login?_format=json" login_response = requests.post( login_url, json={"name": self.USERNAME, "pass": self.PASSWORD}, headers={"Content-Type": "application/json"} ) if login_response.status_code == 200: self.session_cookies = login_response.cookies def get_csrf_token(self): # CSRFトークンを取得 csrf_token_response = requests.get( f"{self.DRUPAL_BASE_URL}/session/token", cookies=self.session_cookies # ここでログインセッションを渡す ) if csrf_token_response.status_code == 200: # return csrf_token_response.text # self.csrf_token = csrf_token_response.text self.headers = { "Content-Type": "application/vnd.api+json", "Accept": "application/vnd.api+json", "X-CSRF-Token": csrf_token_response.text, } else: # raise Exception(f"CSRFトークン取得失敗: {csrf_token_response.status_code} {csrf_token_response.text}") self.csrf_token = None def upload_file(self, type, uuid, field, file_path, verbose=False): url = f"{self.DRUPAL_BASE_URL}/jsonapi/node/{type}/{uuid}/{field}" # ファイル名を取得 filename = os.path.basename(file_path) # ファイルをバイナリモードで読み込む with open(file_path, 'rb') as f: file_data = f.read() headers = self.headers.copy() headers['Content-Type'] = 'application/octet-stream' headers['Content-Disposition'] = f'attachment; filename="{filename}"' # ファイルをアップロード response = requests.post(url, headers=headers, cookies=self.session_cookies, data=file_data) if response.status_code == 200: if verbose: print(f"ファイルアップロード成功: {filename}") else: print(f"ファイルアップロード失敗: {response.status_code} {response.text}") すでに対象コンテンツが作成済みで、例えばfield_fileといったフィールドにファイルをアップロードする目的で使用することができます。 ...

DrupalのSortableviewsモジュールを使って、コンテンツを並び替えて、その結果をフィールドに保存する

DrupalのSortableviewsモジュールを使って、コンテンツを並び替えて、その結果をフィールドに保存する

概要 DrupalのSortableviewsモジュールを使って、コンテンツを並び替えて、その結果をフィールドに保存する方法について紹介します。 https://www.drupal.org/project/sortableviews 以下のように説明されています。 This one is similar to Draggableview module except it can save the position value ( After drag and drop the question ) into custom content type field. これは DraggableViews モジュールと似ています が、ドラッグ&ドロップで並び替えた後の 位置情報をカスタムコンテンツタイプのフィールドに保存できる 点が異なります。 インストール 通常の方法でインストールできました。 コンテンツタイプの作成 ソート対象のコンテンツタイプを作成します。ここでは、teamというコンテンツタイプを対象にします。 そして並び順の重みを保存するためのweightフィールドを作成しました。 Viewsの作成 作成したViewsは以下です。 まず、フォーマットを「Sortable table」にします。この時、field to use for weightの項目で、重みを保存したいフィールドを選択します。 次に、フィールドで「Sortableviews: Drag and drop …」を追加します。これにより、以下のようにドラッグ&ドロップのためのアイコンが表示されます。 さらに、並び替え基準として、「weight(昇順)」に設定しておきます。 最後、ヘッダーの部分で、「Save Sortableviews changes」を追加します。これにより、並び替え後に、「変更を保存」ボタンが表示されます。 APIからの利用 今回の設定では、ソート結果はfield_weightに保存されるため、例えば以下のようにAPIから利用できます。 /jsonapi/node/team?sort=field_weight 昇順に並び替えた結果を取得できます。これにより、decoupledな構成でもソート結果を利用することができます。 ...

Next.js for Drupal の BASE_PATH 問題と修正方法(patch-package活用)

Next.js for Drupal の BASE_PATH 問題と修正方法(patch-package活用)

概要 Next.js for Drupalのv2.0.0が2025/2/11にリリースされました。 https://next-drupal.org/ https://next-drupal.org/blog/next-drupal-2-0 早速試してみたところ、BASE_PATHの取り扱いについて対応が必要だったので、備忘録です。 環境変数 環境変数のサンプルは以下のようになっています。 # See https://next-drupal.org/docs/environment-variables # Required NEXT_PUBLIC_DRUPAL_BASE_URL=https://site.example.com NEXT_IMAGE_DOMAIN=site.example.com # Authentication DRUPAL_CLIENT_ID=Retrieve this from /admin/config/services/consumer DRUPAL_CLIENT_SECRET=Retrieve this from /admin/config/services/consumer # Required for On-demand Revalidation DRUPAL_REVALIDATE_SECRET=Retrieve this from /admin/config/services/next この時、NEXT_PUBLIC_DRUPAL_BASE_URLにhttps://site.example.com/xxxのようなベースパスを含めた形で指定すると、APIのリクエストはhttps://site.example.com/jsonapi/などに送られ、リソースを正しく取得できませんでした。 原因 エラーが発生しているgetResourceCollectionを確認したところ、問い合わせ先のURLを作成するbuildUrl関数において、new URL(path, this.baseUrl);が使用されていました。 ... buildUrl(path, searchParams) { const url = new URL(path, this.baseUrl); const search = ( // Handle DrupalJsonApiParams objects. searchParams && typeof searchParams === "object" && "getQueryObject" in searchParams ? searchParams.getQueryObject() : searchParams ); if (search) { url.search = stringify(search); } return url; } ... async buildEndpoint({ locale = "", path = "", searchParams } = {}) { const localeSegment = locale ? `/${locale}` : ""; if (path && !path.startsWith("/")) { path = `/${path}`; } return this.buildUrl( `${localeSegment}${this.apiPrefix}${path}`, searchParams ).toString(); } ... async getResourceCollection(type, options) { options = { withAuth: this.withAuth, deserialize: true, ...options }; const endpoint = await this.buildEndpoint({ locale: options?.locale !== options?.defaultLocale ? options.locale : void 0, resourceType: type, searchParams: options?.params }); this.debug(`Fetching resource collection of type ${type}.`); const response = await this.fetch(endpoint, { withAuth: options.withAuth, next: options.next, cache: options.cache }); await this.throwIfJsonErrors( response, "Error while fetching resource collection: " ); const json = await response.json(); return options.deserialize ? this.deserialize(json) : json; } ChatGPTに質問したところ、以下の回答が得られました。 ...

DrupalのSearch API Algoliaモジュールを試す

DrupalのSearch API Algoliaモジュールを試す

概要 DrupalのSearch API Algoliaモジュールを試す機会がありましたので、備忘録です。 https://www.drupal.org/project/search_api_algolia インストール Drupal 11では、以下でインストールできました。 composer require 'drupal/search_api_algolia:^3.1' 設定 モジュールのインストール後、サーバとインデックスの設定を行います。 Add server Algoliaの設定画面で確認できる設定情報に基づき、サーバを作成します。ここでは、Write API Keyを使用しました。 Add index インデックスの作成以降は、他のモジュールでの設定と同様です。以下は、Amazon OpenSearch Serviceを使用する例です。 設定後、インデクシングを行います。 結果 以下のように、Drupalへのコンテンツ登録や更新に応じて、Algoliaのインデックスも更新されました。 まとめ このような連携により、Algoliaを用いた高速および柔軟な検索を行うことが可能になりました。 Drupalの活用にあたり、参考になりましたら幸いです。

DrupalのJSON:APIを用いて、ユーザ名とパスワードでデータ登録を行う

DrupalのJSON:APIを用いて、ユーザ名とパスワードでデータ登録を行う

概要 過去に、DrupalのJSON:APIを用いて、Pythonによるデータ登録を行う記事を執筆しました。 以下は、Basic認証を用いた方法です。 また以下は、API Keyを用いた方法です。 これらに加えて、通常のログインによる登録を行うことができたので、備忘録です。 コード 以下の通りです。ログインやCSRFトークンを取得した上で、コンテンツを登録します。 import requests import json import os from dotenv import load_dotenv class ApiClient: def __init__(self): load_dotenv(override=True) # DrupalサイトのURL(例) self.DRUPAL_BASE_URL = os.getenv("DRUPAL_BASE_URL") # エンドポイント(JSON:API) # self.JSONAPI_ENDPOINT = f"{self.DRUPAL_BASE_URL}/jsonapi/node/article" # 認証情報(Basic認証) self.USERNAME = os.getenv("USERNAME") self.PASSWORD = os.getenv("PASSWORD") def login(self): # ログインリクエスト login_url = f"{self.DRUPAL_BASE_URL}/user/login?_format=json" login_response = requests.post( login_url, json={"name": self.USERNAME, "pass": self.PASSWORD}, headers={"Content-Type": "application/json"} ) if login_response.status_code == 200: self.session_cookies = login_response.cookies def get_csrf_token(self): # CSRFトークンを取得 csrf_token_response = requests.get( f"{self.DRUPAL_BASE_URL}/session/token", cookies=self.session_cookies # ここでログインセッションを渡す ) if csrf_token_response.status_code == 200: # return csrf_token_response.text # self.csrf_token = csrf_token_response.text self.headers = { "Content-Type": "application/vnd.api+json", "Accept": "application/vnd.api+json", "X-CSRF-Token": csrf_token_response.text, } else: # raise Exception(f"CSRFトークン取得失敗: {csrf_token_response.status_code} {csrf_token_response.text}") self.csrf_token = None def create_content(self, data: dict): # 記事作成リクエスト url = f"{self.DRUPAL_BASE_URL}/jsonapi/{data['data']['type'].replace('--', '/')}" response = requests.post( # self.JSONAPI_ENDPOINT, url, headers=self.headers, cookies=self.session_cookies, json=data ) if response.status_code == 201: print("コンテンツが作成されました!") else: print("エラー:", response.status_code, response.text) これにより、以下で、コンテンツを登録することができました。 ...

@sidebase/nuxt-authのローカル認証を試す

@sidebase/nuxt-authのローカル認証を試す

概要 @sidebase/nuxt-authのローカル認証を試す機会がありましたので、備忘録です。 背景 以下の記事で、@sidebase/nuxt-authを使って、Drupalの認証を行う方法を紹介しました。 上記の記事では、Nuxt3のSSRを利用して、@sidebase/nuxt-authのauthjsプロバイダを使用していました。プロバイダの説明は以下です。 authjs: for non-static apps that want to use Auth.js / NextAuth.js to offer the reliability & convenience of a 23k star library to the Nuxt 3 ecosystem with a native developer experience (DX) local: for static pages that rely on an external backend with a credential flow for authentication. The Local Provider also supports refresh tokens since v0.9.0. Read more here. (機械翻訳)authjs: 非静的なアプリ向けで、Auth.js / NextAuth.js を使用し、23,000以上のスターを持つ信頼性と利便性をNuxt 3エコシステムに提供します。開発者にネイティブな開発体験 (DX) を提供します。 local: 外部バックエンドを使用し、認証のために資格情報フローを利用する静的ページ向けです。このローカルプロバイダーは、バージョン0.9.0以降、リフレッシュトークンもサポートしています。詳しくはこちらをご覧ください。 ...

Nuxt3と@sidebase/nuxt-authを使って、Drupalの認証を行う

Nuxt3と@sidebase/nuxt-authを使って、Drupalの認証を行う

概要 Nuxt3と@sidebase/nuxt-authを使って、Drupalの認証を行う方法です。 背景 以下の記事で、GakuNin RDMの認証を行う方法を紹介しました。 また、以下の記事で、Next.jsからDrupalのOAuthを利用する方法を紹介しました。 これらを参考にして、Nuxt3からDrupalのOAuthを利用します。 方法 ソースコードは以下のリポジトリでご確認いただけます。 https://github.com/nakamura196/nuxt-rdm 具体的には、以下です。 https://github.com/nakamura196/nuxt-rdm/blob/main/server/api/auth/[…].ts { id: "drupal", name: "Drupal", type: "oauth", clientId: useRuntimeConfig().drupalClientId, clientSecret: useRuntimeConfig().drupalClientSecret, authorization: { url: process.env.DRUPAL_AUTH_URL, params: { scope: process.env.DRUPAL_SCOPE, response_type: "code", redirect_uri: `${ useRuntimeConfig().nextAuthUrl }/api/auth/callback/drupal`, }, }, token: { async request(context) { const body = new URLSearchParams({ client_id: useRuntimeConfig().drupalClientId, client_secret: useRuntimeConfig().drupalClientSecret, code: context.params.code || "", grant_type: "authorization_code", redirect_uri: `${ useRuntimeConfig().nextAuthUrl }/api/auth/callback/drupal`, }); const res = await fetch(process.env.DRUPAL_TOKEN_URL || "", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", }, body, }); const json = await res.json(); // Parse the response body once if (!res.ok) { throw new Error(`Token request failed: ${res.statusText}`); } return { tokens: json }; }, }, profile(profile) { return { id: profile.sub, // "sub" をユーザーの一意のIDとして利用 name: profile.name || profile.preferred_username || "Unknown User", // 名前の優先順位を設定 email: profile.email || "No Email Provided", // メールがない場合のフォールバック image: profile.profile || null, // プロファイルURLを画像として使用(必要に応じて調整) }; }, }, まとめ 間違っている点もあるかもしれませんが、参考になりましたら幸いです。 ...

NextAuth.jsを使ってDrupalのOAuthを利用する

NextAuth.jsを使ってDrupalのOAuthを利用する

概要 NextAuth.jsを使ってDrupalのOAuthを利用する方法に関する備忘録です。 挙動 Next.jsで作成したアプリにアクセスして、「Sign in」ボタンを押します。 Drupalにログインしていない場合には、ログイン画面に遷移します。 ログイン済みの場合、「許可」するかのボタンが表示されるので、許可します。 ログイン情報が表示されます。 Drupal側の準備 モジュールのインストール 以下のモジュールをインストールします。 https://www.drupal.org/project/simple_oauth 本記事執筆時点の最新の以下をインストールしました。 composer require 'drupal/simple_oauth:^6.0@beta' トークンを暗号化するための鍵の生成 鍵のペアを生成し、セキュリティのためにドキュメントルートの外に保存します。 openssl genrsa -out private.key 2048 openssl rsa -in private.key -pubout > public.key 鍵のパスを設定 鍵のパスを管理画面で設定します: /admin/config/people/simple_oauth Amazon LightsailでDrupalを動作させている場合、以下のように、ユーザを変更する必要がありました。 sudo chown daemon:daemon private.key Clients /admin/config/services/consumerにアクセスします。 default_consumerがすでに作成されているため、こちらを編集します。 New Secretに値を入力します。 Grant typesでAuthorization Codeを選択します。 Redirect URIsに以下を入力します。 http://localhost:3000/api/auth/callback/drupal https://oauth.pstmn.io/v1/callback (Postmanでのチェック用) Access token expiration timeに値を入力します。 Postmanでの動作確認 以下のように入力します。Drupalがhttps://drupal.example.orgにセットアップされていると過程します。 認可 URL: https://drupal.example.org/oauth/authorize アクセストークン URL: https://drupal.example.org/oauth/token クライアント ID: Drupalで設定した値 クライアントシークレット: Drupalで設定した値 ...

Drupalのカスタムモジュールで、カスタム権限を使用する

Drupalのカスタムモジュールで、カスタム権限を使用する

概要 Drupalのカスタムモジュールで、カスタム権限を使用する機会がありましたので、備忘録です。 背景 以下の記事で、DrupalからGitHubのActionsを実行するモジュールを紹介しました。 ただし、権限をadminister site configurationに設定しており、管理者権限のユーザしか実行することができませんでした。 この点に対応したコミットは以下です。 https://github.com/nakamura196/Drupal-module-github_webhook/commit/c3b6f57bebfeda0556c929c8ed8ed62a0eb0a5c4 方法 以下、ChatGPT 4oの回答結果を共有します。 Drupalの_permissionには、特定のアクセス権限を設定するための値を設定できます。これによって、特定の役割を持つユーザーが、そのルートにアクセスできるかどうかを制御します。 _permissionに設定できる主な値は以下のようなものです: 一般的な権限 Drupalには、いくつかの標準的な権限が用意されています。以下は一般的に使用される権限の例です: administer site configuration - サイト全体の設定を管理できる権限 access content - コンテンツへのアクセス権限 administer users - ユーザーを管理できる権限 create content - コンテンツを作成できる権限 edit any content - 任意のコンテンツを編集できる権限 delete any content - 任意のコンテンツを削除できる権限 view user profiles - ユーザープロフィールを閲覧できる権限 administer permissions - 権限を管理できる権限 access administration pages - 管理者ページへのアクセス権限 administer taxonomy - タクソノミーを管理できる権限 カスタム権限 モジュール固有の権限を作成することもできます。例えば、github_webhookモジュールに独自の権限を作成し、_permissionで使用することも可能です。 カスタム権限を作成する場合は、github_webhook.permissions.ymlに以下のように権限を定義します: access github webhook settings: title: 'Access GitHub Webhook Settings' description: 'Allows users to access and modify GitHub Webhook settings' restrict access: TRUE そして、routing.ymlでこのカスタム権限を設定します: ...

DrupalからGitHubのActionsを実行するモジュールを作成しました。

DrupalからGitHubのActionsを実行するモジュールを作成しました。

概要 DrupalからGitHubのActionsを実行するモジュールを作成しました。 https://github.com/nakamura196/Drupal-module-github_webhook 以下、使い方について説明します。 使い方 設定 モジュールのインストール後、以下にアクセスします。 /admin/config/github_webhook 以下のような画面に遷移します。 大きく、Respositories とTrigger Webhook に分かれています。 まず、Respositories のRepository 1にGitHub Actionsの実行対象のリポジトリの情報を入力します。Add repositoryやRemove repositoryから、リポジトリの追加と削除を行うことができます。 Event Typeには、GitHub Actions側で設定した値を入力します。初期値のwebhookは、以下のようなActionsを想定しています。 name: Deploy to GitHub Pages on: push: branches: ["main"] workflow_dispatch: repository_dispatch: types: [webhook] permissions: contents: read pages: write id-token: write concurrency: group: "pages" cancel-in-progress: true jobs: build: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v3 ... 設定後、画面下部の送信 ボタンを押して保存します。 ...

DrupalのFacetsで並び順を指定する

DrupalのFacetsで並び順を指定する

概要 DrupalのFacetsで並び順を指定するための備忘録です。 方法 以下にアクセスすることで、ファセットの設定を変更することができます。 /admin/config/search/facets それぞれのファセットで編集ボタンを押すと、以下の画面に遷移します。 画面下部にFacet sorting という項目があり、カウントおよび名前順を設定することができます。名前順にしたい場合には、Sort by countのチェックを外します。 まとめ Drupalの利用にあたり、参考になりましたら幸いです。

DrupalのSearch APIで非公開コンテンツをインデックスしないようにする

DrupalのSearch APIで非公開コンテンツをインデックスしないようにする

概要 DrupalのSearch APIで非公開コンテンツをインデックスしないようにする方法の備忘録です。 参考 以下にも記載がありました。 https://www.acquia.com/jp/blog/introduction-to-search-api-1 方法 以下において、「Entity status」を有効にする必要がありました。 /admin/config/search/search-api/index/xxx/processors まとめ 参考になりましたら幸いです。