ThingsDB Todo アプリのデモについて説明します

WBOY
リリース: 2024-08-06 07:21:12
オリジナル
700 人が閲覧しました

얼마 전 ThingsDB라는 데이터베이스를 발견했습니다. 궁금해서 좀 읽어봤습니다. TCP 연결을 지원하지만 일부 특정 플랫폼용 드라이버가 없다는 사실을 발견했습니다. 따라서 자바스크립트 및 PHP용 드라이버를 개발했습니다.

Javascript 드라이버를 작업하면서 깨달았습니다. 백엔드나 미들웨어 없이 프런트엔드에서 직접 ThingsDB를 사용할 수 있다는 점이었습니다. 브라우저에서 웹소켓(TCP) 연결을 열 수 있으므로 ThingsDB 작성자에게 연락했더니 웹소켓에 대한 지원이 추가되었습니다(ThingsDB 버전 1.6부터 사용 가능). 이렇게 하면 내 자바스크립트 드라이버를 프런트엔드(브라우저)와 자바스크립트 기반 백엔드(예: node.js)에서 사용할 수 있습니다. 나는 흥미로운 피드백을 받은 PHP 드라이버에 관한 기사를 여기에 썼습니다. 사람들은 ThingsDB의 잠재력을 더 많이 보고 싶어했습니다. 이에 따라 나는 자바스크립트 드라이버에 대한 기사를 마친 후 바로 쓰지 않기로 결정했지만 데모를 만드는 것이 가장 좋을 것이라고 결정했습니다.

ThingsDB와 이 데모의 기본 사항을 이해하려면 특정 기능을 설명하는 동안 계속해서 읽어 보시기 바랍니다.당신은 적어도 기본적인 프로그래밍 전반에 익숙할 것으로 예상됩니다. 그리고 아마도 자바스크립트와 jQuery도 있을 것입니다.

ThingsDB 내부에서 코드 스니펫을 실행하여 이 글을 따라하려면 설치 가이드에 언급된 첨부된 docker 파일을 사용해야 합니다.


ThingsDB 구조 소개

먼저 해야 할 일. 간단히 구조를 설명하겠습니다.

ThingsDB에는 컬렉션이 포함되어 있습니다. 컬렉션에는 데이터, 프로시저, 작업, 데이터 유형 및 열거형이 포함됩니다. 사용자 액세스 계정을 포함하고 프로시저와 작업도 포함할 수 있는 사전 컬렉션(범위) @thingsdb도 있습니다. 마지막으로 지금은 중요하지 않은 @node 범위가 있습니다.

  • 데이터 - 영구 저장된 데이터
  • 프로시저 - 함수와 마찬가지로 인수를 가질 수 있고 값을 반환할 수 있습니다
  • 작업 - cron과 같은 계획된 이벤트
  • 데이터 유형 - 클래스와 마찬가지로 속성과 메서드를 가질 수 있습니다
  • 열거형 - 열거자

데이터, 프로시저, 작업, 데이터 유형 및 열거형과 같은 명명된 모든 항목은 ThingsDB를 구현하는 개발자가 정의합니다. 이 데이터베이스의 새 인스턴스에는 @:stuff라는 빈 컬렉션과 사용자 계정 admin만 포함되어 있습니다. 저는 이 컬렉션을 이 데모의 주요 컬렉션으로 사용합니다.

자신과 대화하기

ThingsDB에서 쿼리를 실행하거나 프로시저를 실행할 때 실행할 컬렉션을 지정해야 합니다. 때로는 제한적일 수 있으며 다른 컬렉션에서 쿼리를 실행하거나 프로시저를 실행해야 하는 경우 이를 달성하는 방법이 있습니다. 특정 사용자로서 컬렉션의 다른 컬렉션에 액세스할 수 있게 해주는 thingsdb(book, GitHub)라는 모듈이 있습니다. 내 데모에서는 사용자 계정을 처리할 때 이 기능을 많이 사용하므로 여기서 언급합니다. 매뉴얼에 설명된 대로 이 모듈을 설치했습니다.

권한에 대해서는 나중에 설명하겠지만 참고로 이 모듈을 위해 만든 사용자 계정에는 @thingsdb 컬렉션에 대한 쿼리, 변경, 부여 권한과 @:stuff 컬렉션에 대한 변경, 부여 권한이 있습니다.

사용자 계정

ThingsDB만 사용하기로 결정했기 때문에 해당 사용자 계정을 사용해야 했습니다. 백엔드가 없기 때문에 등록과 로그인을 처리해야 했는데 조금 까다로웠습니다. 물론 제3자 인증 서버(auth0 등)를 사용할 수도 있지만 다른 것에 의존하고 싶지는 않았습니다.

누군가 타사 인증 시스템을 구현하려는 경우 요청 모듈(도서, GitHub)을 사용하여 ThingsDB에서 HTTP 요청을 수행할 수 있습니다.

사용자가 등록할 수 있도록 하려면 ThingsDB와 통신하고 등록을 실행하기 위한 사용자 계정이 필요했습니다. 하지만 이 계정에 필요한 자격 증명은 매우 안전하지 않은 자바스크립트 코드로 게시됩니다. 모든 보안 문제를 다루고 싶지는 않았지만 최소한 간단한 보안 문제라도 구현하고 싶었습니다. ThingsDB는 각 컬렉션에 대해 각 사용자 계정에 대한 권한 부여를 구체적으로 지원합니다. 부여할 수 있는 권한은 쿼리, 변경, 부여, 가입 및 실행입니다.

  • Query - ThingsDB 쿼리
  • 변경 - 데이터를 변경하는 코드 실행을 허용합니다
  • Grant - 권한 부여 허용
  • 가입 - 룸 참여 허용
  • 실행 - 저장 프로시저 실행

Query를 전혀 사용할 수 없습니다. 이 명령을 사용하면 ThingsDB에서 무엇이든 실행할 수 있으며 이를 클라이언트 브라우저에 열면 큰 보안 문제가 발생할 수 있습니다. 경로는 명확했고 절차를 사용해야 했으며 클라이언트에 대해Run만 허용해야 했습니다.

알아두어야 할 중요한 정보는 사용자 계정에 비밀번호뿐만 아니라 액세스 토큰도 있다는 것입니다(필요한 경우 만료됨).

등록을 위해 ThingsDB 준비

나는 컬렉션 @:auth와 이름이 aa(auth 계정)인 사용자 계정을 만들었고 그에게 이 컬렉션에 대한Run권한을 부여했습니다. 컬렉션 @:auth에는 Register라는 프로시저가 하나만 포함되어 있습니다. 이 모든 것은 사용자 aa가 등록이라는 프로시저를 실행하는 한 가지 작업만 수행할 수 있음을 의미합니다. 따라서 그의 액세스 토큰이 게시될 수 있습니다.

프로시저 등록은 새 계정을 생성하고 필요한 권한을 부여합니다. 코드는 다음과 같습니다:

으아악

ThingsDB의 코드를 처음 보는 것 같아요. 약간만 변경해도 다른 프로그래밍 언어에 익숙합니다. 절차의 역할:

  • 두 가지 인수를 허용합니다
  • 인수 이메일 및 비밀번호 확인
  • 쿼리 실행을 위해 혼잣말하기 섹션에 설명된 모듈 thingsdb를 사용하세요.
    • 이미 등록된 이메일인지 확인하세요
    • 새 사용자 계정을 만들고 비밀번호를 설정하세요
    • 필수 권한 부여

email: 약간 혼란스러울 수 있지만 변수를 인수에 전달하고 인수와 변수의 이름이 같을 때 간략하게 설명합니다.

@t는 @thingsdb 범위의 단축어입니다.

등록의 프런트엔드 구현

ThingsDB 측의 모든 준비를 마치고 등록 양식과 몇 줄의 자바스크립트로 간단한 웹사이트를 만들었습니다. ThingsDB 내부에서 프로시저를 실행하는 코드 조각은 다음과 같습니다.

으아악
  1. 토큰으로 인증을 수행합니다(aa 사용자 계정의 경우)
  2. 프로시저 레지스터 실행

브라우저 localStorage에 사용자 aa의 액세스 토큰을 보관합니다.

전체 구현을 보려면 여기를 보세요:

  • register.html
  • register.js

로그인

사용자가 등록할 수 있게 된 후 다음 단계는 로그인 작업을 구현하는 것이었습니다. 로그인하려면 비밀번호가 필요하지만 브라우저에 사용자 비밀번호를 저장하는 것은 그리 안전하지 않습니다. 해결책은 로그인 후 액세스 토큰(만료 포함)을 생성하고 이를 클라이언트에 반환하여 브라우저(예: sessionStorage)에 저장할 수 있는 것입니다. 그래서 등록된 사용자 계정에 필요한 권한이 있는 @:stuff 컬렉션에 프로시저를 만들었습니다.

으아악

토큰 생성은 @thingsdb 범위에서 호출되어야 하며, 이 경우 thingsdb 모듈을 다시 사용합니다. 이 프로시저를 호출하는 자바스크립트 코드 조각은 다음과 같습니다.

으아악

얻은 액세스 토큰은 sessionStorage에 저장됩니다.

여기에서 로그인 양식과 필수 자바스크립트 코드가 포함된 전체 로그인 페이지를 확인할 수 있습니다:

  • index.html
  • index.js

개요

로그인 후 사용자는 일부 계정 작업과 할 일 목록이 있는 여기로 리디렉션됩니다. 이는 구조를 지정하고 Todo 데이터가 저장되는 방법을 지정하는 데 필요하며 이 목적을 위해 데이터 유형을 사용할 수 있습니다. 이름, user_id 및 항목이 있는Todo유형을 만들었습니다.Item유형에는 설명, 확인된 상태 및Todo참조가 있습니다.TodoItem사이의 연결은 양방향 관계(책, 문서)로 이루어집니다. 두 유형 모두 @:stuff 컬렉션에 정의되어 있습니다.

으아악

이 코드에서는 유형이 어떻게 만들어지는지, 데이터 유형에 어떤 속성이 있는지, 그리고 유형 간의 관계가 설정되는지 확인할 수 있습니다.

하지만 이것은 단지 정의일 뿐입니다. Todo를 어딘가에 저장해야 합니다. 이를 위해 우리는 이와 같이 @:stuff 컬렉션에 직접 속성을 만듭니다. 점이 없으면 가변적일 뿐 지속성이 없습니다.

으아악

이제 데이터 구조가 준비되었으면 각 작업을 살펴보겠습니다.

할일

개요 페이지 로딩 시 사용자의 Todo를 ThingsDB에 로딩하도록 요청합니다. 먼저 Todos 목록을 반환하는 @:stuff 컬렉션에 대한 절차가 필요합니다.

으아악

필터는 촬영장에서 호출할 수 있는 기능입니다.

이제 다음과 같이 자바스크립트 코드 조각을 사용하여 이 프로시저를 호출할 수 있습니다(수신된 데이터 처리는 생략됨).

으아악

여기에서 전체 구현을 확인할 수 있습니다:

  • overview.html
  • overview.js

비밀번호 변경

이 작업을 위해 thingsdb 모듈을 다시 사용해야 하는 update_password 프로시저를 만들었습니다. 사용자 계정은 @thingsdb 범위에 저장됩니다.

으아악

저는 html 대화 상자 태그를 사용하여 새 비밀번호를 입력하고 이를 처리하는 자바스크립트 코드 조각은 매우 간단합니다.

으아악

Todos 로드 요청에서 웹소켓 연결이 아직 열려 있기 때문에 authToken을 다시 호출할 필요가 없습니다.

여기에서 전체 구현을 확인할 수 있습니다:

  • overview.html
  • overview.js

계정 삭제

이 작업을 수행하면 사용자 계정뿐만 아니라 해당 사용자의 할일도 제거됩니다. 다음과 같습니다:

new_procedure('delete_user', || { email = user_info().load().name; if (is_email(email)) { .todos.remove(|todo| todo.user_id == user_id); thingsdb.query('@t', 'del_user(email);', {email: }); }; });
ログイン後にコピー

Remove is another function which can be called on set.

I had to use thingsdb module again. User accounts are stored in @thingsdb scope.

Call of this procedure can be done easily with javascript code snippet:

thingsdb.run('@:stuff', 'delete_user')
ログイン後にコピー

I don't have to call authToken again because websocket connection is still open from the request to load Todos.

Look at the whole implementation here:

  • overview.html
  • overview.js

Create Todo

User need a way to create new Todo. For that reason I made page new_todo and overview contains link to it. Form to create todo consist of todo name and items (descriptions). I decided to store new Todo with items in two steps, because originally I wanted to allow editing of Todo (which in the end didn't happen). Therefore I've created two new procedures.

new_procedure('create_todo', |name| { t = Todo{ name:, user_id: user_info().load().user_id, }; .todos.add(t); t.id(); }); new_procedure('add_todo_items', |todo_id, items| { todo = thing(todo_id); if (todo.user_id != user_info().load().user_id) { raise('Not yours'); }; todo.items.clear(); items.each(|i| { item = Item{ checked: false, description: "i," }; todo.items.add(item); }); });
ログイン後にコピー

First procedure to create todo returns it's id and second procedure deletes all items and adds new ones. I think if you read until here you are already getting hang of it and I don't have to explain .todos.add() or items.each() (set add, thing each).

What is new here is thing(todo_id). You can get reference to any thing (thing is like instance of class/data type) from collection by id. You don't have to know where is stored, you can just get it. Thing has assigned id when is stored persistently.

To perform defined action you just have to call it with javascript code snippet:

thingsdb.run('@:stuff', 'create_todo', [$('#name').val()]) .then((todo) => thingsdb.run('@:stuff', 'add_todo_items', [ todo, items.length ? items.map(function () { return $(this).val(); }).get() : [] ]))
ログイン後にコピー

Look at the whole implementation here:

  • new_todo.html
  • new_todo.js

Todo detail

Overview page shows list of user Todos. By clicking on it user is redirected to page where he can see Todo items, change their status and delete whole Todo list.

Load Todo data

To load one specific Todo I've created new procedure:

new_procedure('list_todo', |todo_id| { todo = thing(todo_id); if (todo.user_id != user_info().load().user_id) { raise('Not yours'); }; return todo, 2; });
ログイン後にコピー

Now you are propably asking why there is return todo, 2;? With return you can set depth of data you want to return. With number 2 here returned data contains not only Todo itself, but also Items the Todo has relation with.

Because Todo id is passed as uri get parameter, the javascript code snippet to call this procedure looks like this:

thingsdb.run('@:stuff', 'list_todo', [ parseInt(location.search.match(/id=(\d+)/)[1]) ])
ログイン後にコピー

Look at the whole implementation here:
todo.html
todo.js

Change Todo item status

I render todo items as checklist, so to change status of item I've created new procedure:

new_procedure('mark_item', |item_id, checked| { item = thing(item_id); if (item.todo.user_id != user_info().load().user_id) { raise('Not yours'); }; item.checked = checked; nil; });
ログイン後にコピー

Because you can also uncheck, not only check item, javascript code snippet has to be like this:

thingsdb.run('@:stuff', 'mark_item', [ parseInt(this.id), $(this).is(':checked') ])
ログイン後にコピー

Look at the whole implementation here:
todo.html
todo.js

Delete Todo

If we want to delete Todo, we don't have to delete items because they are not stored separately. If Todo is removed, no other reference exists for its items and they are automatically removed.

new_procedure('delete_todo', |todo_id| { todo = thing(todo_id); if (todo.user_id != user_info().load().user_id) { raise('Not yours'); }; .todos.remove(todo); });
ログイン後にコピー

Now the javascript code snippet is simple:

thingsdb.run('@:stuff', 'delete_todo', [ parseInt(location.search.match(/id=(\d+)/)[1]) ])
ログイン後にコピー

Look at the whole implementation here:
todo.html
todo.js

Installation guide

To simplify usage of this demo you can run ThingsDB in docker with Dockerfile. At the end of this file you find required commands as comments. Instance of ThingsDB made with this Dockerfile is based on specific branch which was not yet released and introduces using user_info() inside of collections.

Next simply open install.html which creates everything required in this ThingsDB instance and store access token of aa user to localStorage.


That's it. I hope I gave you basic insight into this technology. If you like my work you can buy me a tea.

Let me explain a ThingsDB Todo app demo

No AI was used to generate this content, only the cover picture.

以上がThingsDB Todo アプリのデモについて説明しますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:dev.to
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!