やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

GitHubアップローダの未解決課題

とりあえずメモ。まとまっていない。自分でも意味不明になりそう。

GitHub.UserRegister.Authentication.Abstract.201704180751

課題

HTTPリクエスト抽象化が微妙。RESTfulやGitHubAPI仕様と関わるので自分だけでは決められない。変えられたらDBやコードも変更せねばならない。一体どこまで抽象化すべきか、どのようにすべきか。

できたこと

  • GitHubAPIの認証用requestsライブラリ引数生成を抽象化した
    • 認証なし, Basic, TwoFactor, OAuth
    • DBからTokenを取得する
    • APIでTokenを生成してDBに登録する
  • APIごとに認証方法を使い分ける
    • RequestParameter.py
  • 認証クラス配列を生成する
    • AuthenticationsCreator.py
      • DBとユーザ名から以下の認証クラス配列を生成する
      • OAuth, TwoFactor/Basicの優先順に作成できるものがあれば作る
  • HTTPメソッド文字列からリクエストメソッドを識別して実行する

できないこと

  • APIごとに必要なHttpHeadersのAccept指定を抽象化する
    • たとえばLicenseAPIはすべてapplication/vnd.github.drax-preview+jsonが必要である
  • GETの引数であるparamsを抽象化する
  • POSTの引数であるdataを抽象化する

paramsやdataはAPIごとに異なる。Pythonの名前付き引数にしたい。それをどのように抽象化すればいいのか。 辞書引数**kwargsならできそうだが、名前や初期値を指定して何を渡せばいいかわかるようにしたい。 引数のバリデートが必要だから抽象化は難しいか。

理想はAPIごとのdataやparamsの代入やバリデート処理を一切書かない上、以下のようにAPIを呼び出せること。

  • GitHubUploader.py
    • Client(AuthenticationCreator(db, username).Create())
      • client.repo.create(name='', desc='', url='', ..., sort='', direct='', per_page=100)
  • GitHubUserRegister.py
    • Client([BasicAuthentication(username, password)])
      • client.auth.create(scopes)
      • client.sshkeys.create()
    • client.SetAuthentications([OAuthAuthentication(token), BasicAuthentication(username, password)])
      • client.users.get(username)
      • client.repo.gets()

GitHub.Upload.GitHubApiClient.Arrangement.201704091611

課題

  • ユーザ名の更新について動作未確認
  • メールアドレスの更新について動作未確認
  • アカウント管理で2FA関連が未実装
    • DB保存未実装
  • ふだん使うTokenに権限がたくさん付与されてしまう
    • 通信傍受などでTokenが漏洩したときに危険(SSH鍵が変更されてしまうかも?)
      • admin:public_keyの権限は初回限りにする
        • SSH鍵設定したらすぐに権限を削除する
        • SSH鍵の更新に必要
          • 更新は削除後に生成することで実現するGitHubAPIの仕様
          • 削除するのにadmin:public_keyの権限が必要である
  • SSH通信確認ができない
    • ssh-keygen -lコマンドで行うのみ。真偽値で取得したい
  • SSH鍵生成時に、任意の値を指定したい
    • 暗号化方式
    • 暗号化強度
  • SSHのconfigを編集したい(定義順などきれいに整形したい)
  • GitHubAPIを叩く認証部分を重複なくスマートに実装したい
    • ./cui/register/command/Inserter.pyUpdater.pyに重複コード多数あるので解消したい
    • /cui/register/github/api/v3/web/serviceのと重複する
      • 認証部分のコードが多数重複している
      • アカウント作成前なので統合できない
  • AccessTokenのScopeGrantの文言を統一したい
    • dqn.sakusakutto.jp/2012/03/database_refactoring.html
  • 各classの密結合を疎結合にしたい

他、気づいた点

テストしていない

単体テストしていない。コードを変えるたびに動作確認くらいはすべきだが、現実にはできない。

毎回、コード変更した箇所と影響範囲を考えて動作確認すべき箇所を特定して確認することができない。

そもそもどう書くべきかを書きながら模索しているから計画も立てられない。言語仕様などの知識や技術がないため、どう実装すればいいかわからないから全体を見通せず設計ができない。だから実装もテストも行きあたりばったり。結果、頻繁にコードが変わり、安定したコードにならない。テストコード以前に実装コードが書けていない。

自分に知識や技術がないせいだが、それをいったらコードが書けず学べず改善しない。とにかくやってみるしかない。結果このザマ。

コード整理

  • ssh-keygenコマンド操作用クラスを作りたい
    • 本当はparamikoなどのPythonライブラリでSSH通信確認までしたかったが、インストールできなかったので妥協する
  • AuthenticationsCreator.py
    • Basic認証またはTwoFactor認証を返すメソッドを作成したい
      • ./cui/register/command/配下の各クラスで同じ処理を書いているので解消したい

改修しないと問題になる可能性がある

  • ツールでAccessTokenを自動作成したが、サイトで削除してしまった。その後、ツールでアップロードしようとしたが、Tokenが存在しないためAPI実行時にエラーが出た
    • SSH鍵についても同様のことが生じうる
      • GitHubアカウントについても同様のことが生じうる

他にもユーザ操作次第で不具合が生じそうなワークフローがないか考えてみたほうがいいか。

  • GitHubUserRegister.pyでinsertサブコマンドのテスト時、途中でエラーになるとAccessTokenが作成されたままになってしまう。途中で異常終了したときはTokenやSSH鍵などAPIで生成したものを削除するようにしたい。残すとセキュリティホールになりうるが、手動で削除するのも面倒。

改修せずとも問題にはならない

  • ./cui/register/command/Inserter.py
    • __CreateRecordAccount()
      • AccountsテーブルのCreatedAtUpdatedAtの値が1970-01-01T00:00:00Z固定になっている。UsersAPIで日時を取得して設定したい
  • ユーザ作成日時取得のついでにプロフィール情報も取得したい
  • 指定ユーザの全リポジトリを再取得したい
  • AccessTokenの権限設定を任意にしたい

作業中に不満だったこと

所感

少しずつ対処していきたい。