--- title: Dev-in.tw 架構規劃 description: Dev-in.tw是一個由HACO和OnCloud聯合構思的專案,打造一個給予台灣得開法者建立個人子網域的平台,提供 A、AAAA、CNAME、URI......等功能。 tag: Website lang: zh-TW --- ![logo](https://www.lazco.dev/images/logo-long.png) # Dev-in.tw 網域網站架構規劃 --- ## 介紹 **Dev-in.tw是一個由HACO和OnCloud聯合構思的專案, 打造一個給予台灣的開發者建立個人子網域的平台, 提供 A、AAAA、CNAME、URI......等功能。** --- ## 發起人 **<a href="http://discord.com/users/508964901415550976" target="_blank">haco.tw</a> <a href="http://discord.com/users/755269122597585018" target="_blank">OnCloud</a>** --- ## 聯絡方式 * 使用Discord私訊 [HACO#8888](http://discord.com/users/508964901415550976) * 加入 [Discord](https://discord.gg/ZvwTZqXjYf) 在聊天之地提出問題 * Instagram搜尋 <a href="https://instagram.com/lazco.dev" target="_blank">lazco.dev</a> 並私訊我們 * 使用電子郵件寄送至 <a href="mailto:lazco.team@gmail.com" target="_blank">lazco.team@gmail.com</a> <br /> 聯絡時請遵守以下規則 * [No Hello](https://www.nohello.com/) * [正確的提出技術問題](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way) --- ## 網站架構 ``` SubdomainName => 子網域名稱如 lazco SubdomainID => 子網域申請後會自動生成的一組ID ``` #### 前端 - 客戶 `GET /` - 首頁 `GET /account` - 查看帳戶 `GET /account/edit` - 編輯帳戶 `GET /login` - 登入帳戶 `GET /logout` - 登出帳戶 `GET /account/verify` - 驗證帳戶 `GET /find?sub={SubdomainName}` - 子網域存在查詢 `GET /domain` - 管理子網域 `GET /domain/register` - 註冊子網域 `GET /domain/edit/{SubdomainID}` - 編輯子網域 <br /> #### 前端 - 管理 `GET /lazco/account` - 管理所有帳戶 `GET /lazco/account/{accountID}` - 管理單一帳戶 `GET /lazco/account/{accountID}/edit` - 編輯帳戶 `GET /lazco/account/{accountID}/verify` - 審查帳戶驗證 `GET /lazco/domain/` - 管理所有子網域 `GET /lazco/domain/verify` - 子網域申請審查列表 `GET /lazco/domain/verify/{SubdomainID}` - 審查單一子網域申請 `GET /lazco/domain/{SubdomainID}` - 管理單一子網域 `GET /lazco/domain/{SubdomainID}/edit` - 編輯子網域 <br /> #### 後端 ##### Tech / Framework - Language: TypeScript - Schema validation: Zod - Framework: NestJS - Database: MongoDB ##### Database schema **1. Domain** ```json { _id: String, // 此欄位為DB自動生成之欄位, will be used as domain id. cloudflare_id: String, // POST到CF後所生成的id,預設 0 name: String, // 子網域名稱 如:lazco description: String, // 子網域介紹 owner: String, // 使用者採用id制抓id獲取資料 verify: Boolean, // true 即代表申請通過,預設為 false status: String, // apply_time: Date, // 申請送出的timestamp last_update: Date, // 最後變更的timestamp,預設同apply_time expire_time: Date, // 到期timestamp,申請通過當下後一年 ssl: String, // Will only be one of ["off", "flexible", "full", "strict"] premium: Boolean, // 是否否為精選子網域 exclusive: Boolean, // 使否為特殊子網域 disable: Boolean, // 是被管理員停用 } ``` **2. User** ```json { _id: String, // 此欄位為DB自動生成之欄位, will be used as user id. githubId: String, // User's Github ID email: String, // User's email name: String, // User's display name. first_name: String, // 申請網域時身份驗證用 last_name: String, // 申請網域時身份驗證用 birth: Date, // 申請網域時身份驗證用 identy_id: String, // 申請網域時身份驗證用 address: String, // 申請網域時身份驗證用 phone: String, // 申請網域時身份驗證用 avatar: String, // Base64 encoded image. description: String, // User's description. domain_names: [String], // e.g. lazco, haco, oncloud. badage: [String], // Just for future. e.g. Premium badage, Domain badage. beta: Boolean, // Just for future. Get beta program. warn: Number, // Admin warning time. disable: Boolean, // Banned premium: Boolean, // Yup, VIP mode. ip: [String], // 記錄使用者 IP create_time: Date, // Account created time. last_update: Date, // Account last edit time. } ``` Rate limit: - `/search` 50reqs / 10min <br /> ##### Github 透過以下網址帶入`code`獲得Github `access_token` https://github.com/login/oauth/access_token <br /> 以下兩個網址皆需帶入 Bearer `access_token` https://api.github.com/user https://api.github.com/user/emails <br /> 如果使用者有很多個email 就挑選primary = true 我們也需要GitHub ID 因為使用者有可能會改primary mail 因此每次登入都要抓取 <br /> 範例程式碼 1 `code get acces_token from github` ```ts= // GITHUB CLIENT ID 和 SECRET 請洽 HACO const github_response = await fetch( "https://github.com/login/oauth/access_token", { method: "POST", headers: { "Content-Type": "application/json", Accept: "application/json", }, body: JSON.stringify({ client_id: process.env.GITHUB_CLIENT_ID, client_secret: process.env.GITHUB_CLIENT_SECRET, scope: "user:email", code, }), } ); const { access_token } = await github_response.json(); ``` <br /> 範例程式碼 2 `acces_token get user info from github` ```ts= const github_user_response = await fetch("https://api.github.com/user", { headers: { Authorization: `Bearer ${access_token}`, }, }); const userData = await github_user_response.json(); ``` <br /> 範例程式碼 3 `acces_token get user email from github` ```ts= const github_user_response = await fetch("https://api.github.com/user", { headers: { Authorization: `Bearer ${access_token}`, }, }); const userData = await github_user_response.json(); ``` <br /> ##### 路由 **Main** `ANY` `/` ```json 200 { message: "Welcome to Dev-in.tw backend API" } ``` `ANY` `/*` ```json 404 { message: "Welcome to Dev-in.tw backend API" } ``` <br /> **Authentication** `POST` `/auth/github` > Pass in Github authentication code, return user's Bearer for dev-in.tw. > Create new user if necessary. > Please refer to [API Document](https://dev-in-tw-api-dev.zeabur.app/docs#/default/GithubController_getGitHubAccountData). <br /> **User** `GET` `/user` List all user, required bearer from lazco team member `PATCH` `/user/${userId}` Update user, required bearer from lazco team member `DELETE` `/user/${userId}` DELETE user, required bearer from lazco member `GET` `/user/info` Required Bearer to get user info `PATCH` `/user/info` Required Bearer to update user info `GET` `/user/info/${userId}` Get user public info <br /> **Domain** `GET` `/domain/find/${SubdomainName}` Search the subdomain. `POST` `/domain/register/${SubdomainName}` Register subdomain. Required user Bearer <br /> dev-in.tw www.dev-in.tw api.dev-in.tw {%hackmd @lazco/dracula %}