【owner登録】チーム作成者を自動でownerとして保存する
このページでやること
このページでは、チームを作った人を、自動で owner として保存する処理を確認します。
owner とは、そのチームの所有者です。
チームを作った人は、そのチームを管理できる人にする必要があります。
そのため、チーム作成時に、次の場所へ自動で保存します。
teams/{teamId}/members/{uid}
保存する内容は、次のようになります。
uid: ログイン中ユーザーのuid
email: ログイン中ユーザーのメール
displayName: ログイン中ユーザーの名前
role: owner
joinedAt: 参加日時
今日のゴール
チームを作った人が、自動で owner として登録されるようにします。
ログイン中のユーザーがチームを作る
↓
teams/{teamId} を作る
↓
teams/{teamId}/members/{uid} を作る
↓
role に owner を保存する
この role: owner がとても大事です。
このページで出てくる単語
| 単語 | 一言説明 |
|---|---|
owner | チームの所有者 |
role | その人の権限 |
uid | ユーザーごとのID |
members | チームに参加している人の一覧 |
doc(user.uid) | ユーザーIDを使って保存場所を決める |
set() | 指定した場所にデータを保存する |
joinedAt | チームに参加した日時 |
権限とは、その人が何をできるかを決めるルールです。
npmや環境変数はこのページで必要?
このページでは、npmは使いません。
環境変数も設定しません。
必要なのは、すでに使っている次の2つです。
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
このページでは、Firestoreへ owner を保存する部分だけを確認します。
Step 1:main.dartを開く
次のファイルを開きます。
lib/main.dart
ターミナルから開く場合は、次を実行します。
code lib/main.dart
code が使えない場合は、VS Codeの左側から lib/main.dart を開いてください。
Step 2:createTeam()を探す
main.dart の中で、次の関数を探します。
createTeam
VS Codeでは、次で検索できます。
command + F
検索する文字はこれです。
Future<void> createTeam
この createTeam() が、チームを作る処理です。
Step 3:ログイン中ユーザーを取得する
createTeam() の中に、次のコードがあるか確認します。
final user = FirebaseAuth.instance.currentUser;
currentUser は、今ログインしているユーザーです。
この user から、uid やメールアドレスを取得します。
user.uid
user.email
uid は、ユーザーごとにFirebaseが作るIDです。
Step 4:ログインしていない場合を止める
次のコードも確認します。
if (user == null) {
setSheetState(() {
errorText = 'ログイン状態を確認できません。';
});
return;
}
user == null は、ログイン中のユーザーがいないという意味です。
ログインしていない人はチームを作れないので、ここで処理を止めます。
return は、ここで処理を終了するという意味です。
Step 5:ユーザーのプロフィールを取得する
次に、users/{uid} からプロフィールを取得します。
final userDoc = await FirebaseFirestore.instance
.collection('users')
.doc(user.uid)
.get();
final userData = userDoc.data();
これは、前に保存したプロフィールを読み込む処理です。
users/{uid}
displayName
email
department
ここから、チームメンバーとして保存する名前とメールを取り出します。
Step 6:displayNameとemailを作る
次のコードを確認します。
final displayName = (userData?['displayName'] ?? user.email ?? '名無し')
.toString();
final email = (userData?['email'] ?? user.email ?? '').toString();
意味はこうです。
displayName があれば使う
↓
なければ user.email を使う
↓
それもなければ「名無し」にする
?? は、左側がなければ右側を使うという意味です。
Step 7:teams/{teamId} を作る
まず、チーム本体を作ります。
final teamRef = await FirebaseFirestore.instance.collection('teams').add({
'name': teamName,
'ownerId': user.uid,
'memberIds': [user.uid],
'createdAt': FieldValue.serverTimestamp(),
'updatedAt': FieldValue.serverTimestamp(),
});
ここでは、teams に新しいチームを作っています。
大事なのは、この2つです。
'ownerId': user.uid,
'memberIds': [user.uid],
ownerId は、チームを作った人のIDです。
memberIds は、チームに参加している人のID一覧です。
作った本人は、最初から参加メンバーなので、memberIds に入れます。
Step 8:members/{uid} にownerとして保存する
ここがこのページの一番大事な部分です。
await teamRef.collection('members').doc(user.uid).set({
'uid': user.uid,
'email': email,
'displayName': displayName,
'role': 'owner',
'joinedAt': FieldValue.serverTimestamp(),
});
このコードで、チーム作成者を owner として保存します。
保存先はここです。
teams/{teamId}/members/{uid}
つまり、作成したチームの中に、作成者のメンバー情報を作ります。
Step 9:role: owner の意味
この部分を見ます。
'role': 'owner',
role は、その人の権限です。
owner は、チームの所有者です。
たとえば、今後このような判断に使えます。
ownerなら
↓
メンバー追加できる
タスク削除できる
チーム設定を変更できる
viewerなら
↓
見るだけ
このように、role を保存しておくと、あとで権限管理ができます。
Step 10:完成形のcreateTeam()
createTeam() は、次の形になっていればOKです。
Future<void> createTeam(StateSetter setSheetState) async {
final user = FirebaseAuth.instance.currentUser;
if (user == null) {
setSheetState(() {
errorText = 'ログイン状態を確認できません。';
});
return;
}
final teamName = teamNameController.text.trim();
if (teamName.isEmpty) {
setSheetState(() {
errorText = 'チーム名を入力してください。';
});
return;
}
setSheetState(() {
isCreating = true;
errorText = null;
});
try {
final userDoc = await FirebaseFirestore.instance
.collection('users')
.doc(user.uid)
.get();
final userData = userDoc.data();
final displayName =
(userData?['displayName'] ?? user.email ?? '名無し').toString();
final email = (userData?['email'] ?? user.email ?? '').toString();
final teamRef = await FirebaseFirestore.instance.collection('teams').add({
'name': teamName,
'ownerId': user.uid,
'memberIds': [user.uid],
'createdAt': FieldValue.serverTimestamp(),
'updatedAt': FieldValue.serverTimestamp(),
});
await teamRef.collection('members').doc(user.uid).set({
'uid': user.uid,
'email': email,
'displayName': displayName,
'role': 'owner',
'joinedAt': FieldValue.serverTimestamp(),
});
if (mounted) {
Navigator.of(context).pop();
}
} on FirebaseException catch (e) {
setSheetState(() {
errorText = e.message ?? 'チーム作成に失敗しました。';
});
} catch (_) {
setSheetState(() {
errorText = 'チーム作成に失敗しました。';
});
} finally {
if (mounted) {
setSheetState(() {
isCreating = false;
});
}
}
}
Step 11:保存する
main.dart を保存します。
Macの場合:
command + S
Windowsの場合:
Ctrl + S
Step 12:実行する
ターミナルで実行します。
flutter run
すでに起動している場合は、ターミナルで r を押します。
r
うまく反映されない場合は、R でホットリスタートします。
R
Step 13:チームを作って確認する
アプリでログインします。
右下の + ボタンを押します。
+ ボタン
↓
チーム名を入力
↓
作成する
例:
開発チーム
作成できたら、Firebase Consoleで確認します。
Step 14:Firestoreでownerを確認する
Firebase Consoleを開きます。
https://console.firebase.google.com/
次の順番で確認します。
Firestore Database
↓
データ
↓
teams
↓
作成したteamId
↓
members
↓
自分のuid
中身に、次があれば成功です。
uid
email
displayName
role: owner
joinedAt
特に見るのはここです。
role: owner
これが保存されていれば、このページのゴール達成です。
なぜowner登録が必要なのか
チームを作っただけでは、誰が管理者なのか分かりません。
そのため、作成者を owner として保存します。
チームを作る
↓
作成者をownerにする
↓
あとで権限チェックできる
たとえば、今後こういう処理ができます。
ownerだけがメンバーを追加できる
ownerだけがチーム設定を変更できる
ownerとadminだけがタスクを削除できる
viewerは見るだけ
role を保存しておくことで、チーム内のルールを作れるようになります。
よくあるエラーと直し方
| エラー | 原因 | 直し方 |
|---|---|---|
FirebaseAuth isn't defined | importがない | firebase_auth.dart をimportする |
FirebaseFirestore isn't defined | importがない | cloud_firestore.dart をimportする |
FieldValue isn't defined | importがない | cloud_firestore.dart をimportする |
permission-denied | Firestore Rulesで拒否されている | 開発用Rulesを確認する |
role が保存されない | members の set() がない | teamRef.collection('members').doc(user.uid).set() を確認 |
role が member になる | 値を間違えている | 'role': 'owner' にする |
members が作られない | teamRef のあとに保存処理がない | teamRef.collection('members') を確認 |
permission-denied** が出たとき**
開発中だけ、Firestore Rulesを次のようにして確認できます。
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if true;
}
}
}
これは学習用です。
本番公開では使わないでください。
本番では、ログインユーザーやチームメンバーだけが必要なデータを読み書きできるようにします。
members** が作られないとき**
次のコードがあるか確認してください。
await teamRef.collection('members').doc(user.uid).set({
'uid': user.uid,
'email': email,
'displayName': displayName,
'role': 'owner',
'joinedAt': FieldValue.serverTimestamp(),
});
特に、この部分が大切です。
'role': 'owner',
また、teamRef を作ったあとに書いているか確認します。
final teamRef = await FirebaseFirestore.instance.collection('teams').add({...});
await teamRef.collection('members').doc(user.uid).set({...});
この順番で書きます。
最短作業まとめ
読むのが大変な人は、ここだけ見てください。
1. チーム作成者のuidを取得
final user = FirebaseAuth.instance.currentUser;
2. teams/{teamId} を作る
final teamRef = await FirebaseFirestore.instance.collection('teams').add({
'name': teamName,
'ownerId': user.uid,
'memberIds': [user.uid],
'createdAt': FieldValue.serverTimestamp(),
'updatedAt': FieldValue.serverTimestamp(),
});
3. members/{uid} にownerとして保存
await teamRef.collection('members').doc(user.uid).set({
'uid': user.uid,
'email': email,
'displayName': displayName,
'role': 'owner',
'joinedAt': FieldValue.serverTimestamp(),
});
4. 保存して実行
flutter run
チェックリスト
□ main.dartを開いた
□ createTeam()を探した
□ currentUserでログイン中ユーザーを取得した
□ users/{uid} からプロフィールを取得した
□ teams/{teamId} を作った
□ ownerIdにuser.uidを入れた
□ memberIdsにuser.uidを入れた
□ members/{uid} を作った
□ roleにownerを入れた
□ joinedAtを入れた
□ 保存した
□ flutter runで起動した
□ Firestoreでrole: ownerを確認した
ミニ確認問題
Q1. チーム作成者の role は何にしますか?
回答
owner にします。
チームを作った人は、そのチームの所有者だからです。
Q2. members/{uid} には何を保存しますか?
回答
チーム内でのメンバー情報を保存します。
今回なら、uid、email、displayName、role、joinedAt を保存します。
Q3. なぜ ownerId と members/{uid} の両方に保存しますか?
回答
ownerId は、チームの作成者をすぐ確認するために使います。
members/{uid} は、チーム内での権限や表示名を管理するために使います。
役割が違うため、両方保存します。
Q4. このページでnpmや環境変数は必要ですか?
回答
必要ありません。
このページでは、チーム作成者を owner としてFirestoreに保存するだけです。
このページのまとめ
- チームを作った人は、自動で
ownerとして保存する。 ownerは、チームの所有者という意味。teams/{teamId}にはownerIdとmemberIdsを保存する。teams/{teamId}/members/{uid}にはrole: ownerを保存する。roleは、あとで権限管理に使う。ownerを保存しておくと、メンバー追加・削除・チーム管理などを制御できる。- このページではnpmや環境変数は不要。
次のページでやること
次のページでは、自分が参加しているチームだけを一覧表示します。
where('memberIds', arrayContains: uid) を使って、ログイン中ユーザーのチームを取得します。
