{
  "version": "1.4",
  "metadata": {
    "app": "nytem-2021/appland",
    "language": {
      "name": "ruby",
      "engine": "ruby",
      "version": "2.6.6"
    },
    "client": {
      "name": "appmap",
      "url": "https://github.com/applandinc/appmap-ruby",
      "version": "0.42.0"
    },
    "frameworks": [
      {
        "name": "rails",
        "version": "5.2.4.2"
      },
      {
        "name": "rspec",
        "version": "3.9.1"
      }
    ],
    "git": {
      "repository": "git@github.com:applandinc/appland.git",
      "branch": "swagger",
      "commit": "8133d5f99aba206c6ae46645d02624360decba7a",
      "status": [
        "M swagger/openapi.yaml",
        "?? 20210310072459.appmap.json"
      ],
      "git_last_annotated_tag": null,
      "git_last_tag": "v0.22.0",
      "git_commits_since_last_annotated_tag": null,
      "git_commits_since_last_tag": 0
    },
    "name": "API::APIKeysController create a new api key",
    "source_location": "spec/requests/api_api_keys_spec.rb",
    "recorder": {
      "name": "rspec"
    },
    "fingerprints": [
      {
        "appmap_digest": "5b77efd1e42d07af30b39e4d6cff328e999580bb5f84c2fbb4e27ada0cd0dd6a",
        "canonicalization_algorithm": "update_v1",
        "digest": "f764239f8e044f9cf68e583220fd277322d852a01b6b88fa4161563cfaa7ff15",
        "fingerprint_algorithm": "sha256"
      },
      {
        "appmap_digest": "5b77efd1e42d07af30b39e4d6cff328e999580bb5f84c2fbb4e27ada0cd0dd6a",
        "canonicalization_algorithm": "info_v1",
        "digest": "d5528102a595bb74564a045db1b3bbf4dbb0f37b4f2f85fc26b90384587922ac",
        "fingerprint_algorithm": "sha256"
      },
      {
        "appmap_digest": "5b77efd1e42d07af30b39e4d6cff328e999580bb5f84c2fbb4e27ada0cd0dd6a",
        "canonicalization_algorithm": "trace_v1",
        "digest": "b704de5f0e6da8f83f501351c22bbe53873b3f721050e3a8d4731b78f467b152",
        "fingerprint_algorithm": "sha256"
      }
    ]
  },
  "classMap": [
    {
      "name": "app/models",
      "type": "package",
      "children": [
        {
          "name": "ApiKey",
          "type": "class",
          "children": [
            {
              "name": "issue",
              "type": "function",
              "location": "app/models/api_key.rb:28",
              "static": true,
              "source": "    def issue(login, description: nil, encode: true)\n      api_key = DAO::ApiKey.new.tap do |api_key|\n        api_key.login = login\n        api_key.description = description if description.present?\n        api_key.save\n      end\n\n      return encode(api_key) if encode\n\n      api_key\n    end\n"
            },
            {
              "name": "encode",
              "type": "function",
              "location": "app/models/api_key.rb:20",
              "static": true,
              "source": "    def encode(api_key)\n      Base64.urlsafe_encode64([api_key.login, api_key.key].join(SEPARATOR), padding: false)\n    end\n"
            },
            {
              "name": "authenticate",
              "type": "function",
              "location": "app/models/api_key.rb:52",
              "static": true,
              "labels": [
                "provider.authentication"
              ],
              "comment": "# @labels provider.authentication\n",
              "source": "    def authenticate(api_key)\n      login, key = decode(api_key)\n      result = DAO::ApiKey.where(login: login).match(key)\n\n      if result.present?\n        touch(result)\n        User::Show.new(result.user)\n      else\n        nil\n      end\n    end\n"
            },
            {
              "name": "decode",
              "type": "function",
              "location": "app/models/api_key.rb:24",
              "static": true,
              "source": "    def decode(api_key)\n      Base64.urlsafe_decode64(api_key).split(SEPARATOR)\n    end\n"
            },
            {
              "name": "touch",
              "type": "function",
              "location": "app/models/api_key.rb:11",
              "static": true,
              "source": "    def touch(api_key)\n      if api_key.last_used.nil? || api_key.last_used > 15.minutes.ago\n        api_key.last_used = Time.now\n        api_key.save_changes\n      end\n\n      api_key\n    end\n"
            }
          ]
        }
      ]
    },
    {
      "name": "action_pack",
      "type": "package",
      "children": [
        {
          "name": "ActionDispatch",
          "type": "class",
          "children": [
            {
              "name": "Cookies",
              "type": "class",
              "children": [
                {
                  "name": "CookieJar",
                  "type": "class",
                  "children": [
                    {
                      "name": "update",
                      "type": "function",
                      "location": "/Users/kgilpin/tmp/appland/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.4.2/lib/action_dispatch/middleware/cookies.rb:344",
                      "static": false,
                      "labels": [
                        "provider.http.cookie"
                      ],
                      "source": "      def update(other_hash)\n        @cookies.update other_hash.stringify_keys\n        self\n      end\n"
                    }
                  ]
                }
              ]
            }
          ]
        }
      ]
    },
    {
      "name": "app/controllers",
      "type": "package",
      "children": [
        {
          "name": "API",
          "type": "class",
          "children": [
            {
              "name": "APIKeysController",
              "type": "class",
              "children": [
                {
                  "name": "create",
                  "type": "function",
                  "location": "app/controllers/api/api_keys_controller.rb:10",
                  "static": false,
                  "source": "    def create\n      new_key = ApiKey.issue(@current_user.login, description: params[:description])\n      render json: { api_key: new_key }, status: :created\n    end\n"
                }
              ]
            }
          ]
        }
      ]
    },
    {
      "name": "json",
      "type": "package",
      "children": [
        {
          "name": "JSON",
          "type": "class",
          "children": [
            {
              "name": "Ext",
              "type": "class",
              "children": [
                {
                  "name": "Generator",
                  "type": "class",
                  "children": [
                    {
                      "name": "State",
                      "type": "class",
                      "children": [
                        {
                          "name": "generate",
                          "type": "function",
                          "location": "JSON::Ext::Generator::State#generate",
                          "static": false,
                          "labels": [
                            "format.json",
                            "provider.serialization"
                          ]
                        }
                      ]
                    }
                  ]
                },
                {
                  "name": "Parser",
                  "type": "class",
                  "children": [
                    {
                      "name": "parse",
                      "type": "function",
                      "location": "JSON::Ext::Parser#parse",
                      "static": false,
                      "labels": [
                        "format.json",
                        "provider.serialization"
                      ]
                    }
                  ]
                }
              ]
            }
          ]
        }
      ]
    }
  ],
  "events": [
    {
      "id": 26687,
      "event": "call",
      "thread_id": 70146500788180,
      "defined_class": "ApiKey",
      "method_id": "issue",
      "path": "app/models/api_key.rb",
      "lineno": 28,
      "static": true,
      "parameters": [
        {
          "name": "login",
          "class": "String",
          "object_id": 70146237309120,
          "value": "admin",
          "kind": "req"
        },
        {
          "name": "description",
          "class": "String",
          "object_id": 70145697080380,
          "value": "example api key",
          "kind": "key"
        },
        {
          "name": "encode",
          "class": "NilClass",
          "object_id": 8,
          "value": null,
          "kind": "key"
        }
      ],
      "receiver": {
        "class": "Class",
        "object_id": 70145695643300,
        "value": "ApiKey"
      }
    },
    {
      "id": 26688,
      "event": "call",
      "thread_id": 70146500788180,
      "sql_query": {
        "sql": "INSERT INTO \"api_keys\" (\"login\", \"description\") VALUES ('admin', 'example api key') RETURNING *",
        "database_type": "postgres",
        "server_version": 120003
      }
    },
    {
      "id": 26689,
      "event": "return",
      "thread_id": 70146500788180,
      "parent_id": 26688,
      "elapsed": 0.001567
    },
    {
      "id": 26690,
      "event": "call",
      "thread_id": 70146500788180,
      "defined_class": "ApiKey",
      "method_id": "encode",
      "path": "app/models/api_key.rb",
      "lineno": 20,
      "static": true,
      "parameters": [
        {
          "name": "api_key",
          "class": "DAO::ApiKey",
          "object_id": 70146233518200,
          "value": "#<DAO::ApiKey:0x00007f9862a990f0>",
          "kind": "req"
        }
      ],
      "receiver": {
        "class": "Class",
        "object_id": 70145695643300,
        "value": "ApiKey"
      }
    },
    {
      "id": 26691,
      "event": "return",
      "thread_id": 70146500788180,
      "parent_id": 26690,
      "elapsed": 0.000023,
      "return_value": {
        "class": "String",
        "value": "YWRtaW46YWNjZTM1YWItMTMyNC00NGM2LTljYTktMTEzZGI0MDY3NTQ5",
        "object_id": 70145699433860
      }
    },
    {
      "id": 26692,
      "event": "return",
      "thread_id": 70146500788180,
      "parent_id": 26687,
      "elapsed": 0.005866,
      "return_value": {
        "class": "String",
        "value": "YWRtaW46YWNjZTM1YWItMTMyNC00NGM2LTljYTktMTEzZGI0MDY3NTQ5",
        "object_id": 70145699433860
      }
    },
    {
      "id": 26693,
      "event": "call",
      "thread_id": 70146500788180,
      "http_server_request": {
        "request_method": "POST",
        "path_info": "/api/api_keys",
        "mime_type": "application/x-www-form-urlencoded",
        "normalized_path_info": "/api/api_keys(.:format)",
        "authorization": "Bearer YWRtaW46YWNjZTM1YWItMTMyNC00NGM2LTljYTktMTEzZGI0MDY3NTQ5"
      },
      "message": [
        {
          "name": "description",
          "class": "String",
          "value": "api test",
          "object_id": 70145699450780
        },
        {
          "name": "controller",
          "class": "String",
          "value": "api/api_keys",
          "object_id": 70146368082620
        },
        {
          "name": "action",
          "class": "String",
          "value": "create",
          "object_id": 70146368035800
        }
      ]
    },
    {
      "id": 26694,
      "event": "call",
      "thread_id": 70146500788180,
      "defined_class": "ActionDispatch::Cookies::CookieJar",
      "method_id": "update",
      "path": "/Users/kgilpin/tmp/appland/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.4.2/lib/action_dispatch/middleware/cookies.rb",
      "lineno": 344,
      "static": false,
      "parameters": [
        {
          "name": "other_hash",
          "class": "Hash",
          "object_id": 70145699452300,
          "value": "{}",
          "kind": "req"
        }
      ],
      "receiver": {
        "class": "ActionDispatch::Cookies::CookieJar",
        "object_id": 70145426893240,
        "value": "#<ActionDispatch::Cookies::CookieJar:0x00007f9802815370>"
      }
    },
    {
      "id": 26695,
      "event": "return",
      "thread_id": 70146500788180,
      "parent_id": 26694,
      "elapsed": 0.000009,
      "return_value": {
        "class": "ActionDispatch::Cookies::CookieJar",
        "value": "#<ActionDispatch::Cookies::CookieJar:0x00007f9802815370>",
        "object_id": 70145426893240
      }
    },
    {
      "id": 26696,
      "event": "call",
      "thread_id": 70146500788180,
      "defined_class": "ApiKey",
      "method_id": "authenticate",
      "path": "app/models/api_key.rb",
      "lineno": 52,
      "static": true,
      "parameters": [
        {
          "name": "api_key",
          "class": "String",
          "object_id": 70145426913340,
          "value": "YWRtaW46YWNjZTM1YWItMTMyNC00NGM2LTljYTktMTEzZGI0MDY3NTQ5",
          "kind": "req"
        }
      ],
      "receiver": {
        "class": "Class",
        "object_id": 70145695643300,
        "value": "ApiKey"
      }
    },
    {
      "id": 26697,
      "event": "call",
      "thread_id": 70146500788180,
      "defined_class": "ApiKey",
      "method_id": "decode",
      "path": "app/models/api_key.rb",
      "lineno": 24,
      "static": true,
      "parameters": [
        {
          "name": "api_key",
          "class": "String",
          "object_id": 70145426913340,
          "value": "YWRtaW46YWNjZTM1YWItMTMyNC00NGM2LTljYTktMTEzZGI0MDY3NTQ5",
          "kind": "req"
        }
      ],
      "receiver": {
        "class": "Class",
        "object_id": 70145695643300,
        "value": "ApiKey"
      }
    },
    {
      "id": 26698,
      "event": "return",
      "thread_id": 70146500788180,
      "parent_id": 26697,
      "elapsed": 0.000014,
      "return_value": {
        "class": "Array",
        "value": "[\"admin\", \"acce35ab-1324-44c6-9ca9-113db4067549\"]",
        "object_id": 70145426909640
      }
    },
    {
      "id": 26699,
      "event": "call",
      "thread_id": 70146500788180,
      "sql_query": {
        "sql": "SELECT * FROM \"api_keys\" WHERE (\"login\" = 'admin')",
        "database_type": "postgres",
        "server_version": 120003
      }
    },
    {
      "id": 26700,
      "event": "return",
      "thread_id": 70146500788180,
      "parent_id": 26699,
      "elapsed": 0.001221
    },
    {
      "id": 26701,
      "event": "call",
      "thread_id": 70146500788180,
      "defined_class": "ApiKey",
      "method_id": "touch",
      "path": "app/models/api_key.rb",
      "lineno": 11,
      "static": true,
      "parameters": [
        {
          "name": "api_key",
          "class": "DAO::ApiKey",
          "object_id": 70145872027340,
          "value": "#<DAO::ApiKey:0x00007f983791bd98>",
          "kind": "req"
        }
      ],
      "receiver": {
        "class": "Class",
        "object_id": 70145695643300,
        "value": "ApiKey"
      }
    },
    {
      "id": 26702,
      "event": "call",
      "thread_id": 70146500788180,
      "sql_query": {
        "sql": "UPDATE \"api_keys\" SET \"last_used\" = '2021-03-26 20:32:37.270574+0000' WHERE (\"id\" = 2)",
        "database_type": "postgres",
        "server_version": 120003
      }
    },
    {
      "id": 26703,
      "event": "return",
      "thread_id": 70146500788180,
      "parent_id": 26702,
      "elapsed": 0.00183
    },
    {
      "id": 26704,
      "event": "return",
      "thread_id": 70146500788180,
      "parent_id": 26701,
      "elapsed": 0.008095,
      "return_value": {
        "class": "DAO::ApiKey",
        "value": "#<DAO::ApiKey:0x00007f983791bd98>",
        "object_id": 70145872027340
      }
    },
    {
      "id": 26705,
      "event": "call",
      "thread_id": 70146500788180,
      "sql_query": {
        "sql": "SELECT * FROM \"users\" WHERE (\"users\".\"login\" = 'admin') LIMIT 1",
        "database_type": "postgres",
        "server_version": 120003
      }
    },
    {
      "id": 26706,
      "event": "return",
      "thread_id": 70146500788180,
      "parent_id": 26705,
      "elapsed": 0.001341
    },
    {
      "id": 26707,
      "event": "return",
      "thread_id": 70146500788180,
      "parent_id": 26696,
      "elapsed": 0.021504,
      "return_value": {
        "class": "User::Show",
        "value": "#<User::Show:0x00007f9837b9ae20>",
        "object_id": 70145873336080
      }
    },
    {
      "id": 26708,
      "event": "call",
      "thread_id": 70146500788180,
      "defined_class": "API::APIKeysController",
      "method_id": "create",
      "path": "app/controllers/api/api_keys_controller.rb",
      "lineno": 10,
      "static": false,
      "parameters": [],
      "receiver": {
        "class": "API::APIKeysController",
        "object_id": 70145699467000,
        "value": "#<API::APIKeysController:0x00007f9822ff9df0>"
      }
    },
    {
      "id": 26709,
      "event": "call",
      "thread_id": 70146500788180,
      "defined_class": "ApiKey",
      "method_id": "issue",
      "path": "app/models/api_key.rb",
      "lineno": 28,
      "static": true,
      "parameters": [
        {
          "name": "login",
          "class": "String",
          "object_id": 70145873336280,
          "value": "admin",
          "kind": "req"
        },
        {
          "name": "description",
          "class": "String",
          "object_id": 70145699450780,
          "value": "api test",
          "kind": "key"
        },
        {
          "name": "encode",
          "class": "NilClass",
          "object_id": 8,
          "value": null,
          "kind": "key"
        }
      ],
      "receiver": {
        "class": "Class",
        "object_id": 70145695643300,
        "value": "ApiKey"
      }
    },
    {
      "id": 26710,
      "event": "call",
      "thread_id": 70146500788180,
      "sql_query": {
        "sql": "INSERT INTO \"api_keys\" (\"login\", \"description\") VALUES ('admin', 'api test') RETURNING *",
        "database_type": "postgres",
        "server_version": 120003
      }
    },
    {
      "id": 26711,
      "event": "return",
      "thread_id": 70146500788180,
      "parent_id": 26710,
      "elapsed": 0.001684
    },
    {
      "id": 26712,
      "event": "call",
      "thread_id": 70146500788180,
      "defined_class": "ApiKey",
      "method_id": "encode",
      "path": "app/models/api_key.rb",
      "lineno": 20,
      "static": true,
      "parameters": [
        {
          "name": "api_key",
          "class": "DAO::ApiKey",
          "object_id": 70145873332300,
          "value": "#<DAO::ApiKey:0x00007f9837b99098>",
          "kind": "req"
        }
      ],
      "receiver": {
        "class": "Class",
        "object_id": 70145695643300,
        "value": "ApiKey"
      }
    },
    {
      "id": 26713,
      "event": "return",
      "thread_id": 70146500788180,
      "parent_id": 26712,
      "elapsed": 0.000019,
      "return_value": {
        "class": "String",
        "value": "YWRtaW46YmRjYzUxODQtOTZhYi00Y2JmLWIyNzctYTBlYzAxZjhmYjI3",
        "object_id": 70146523040500
      }
    },
    {
      "id": 26714,
      "event": "return",
      "thread_id": 70146500788180,
      "parent_id": 26709,
      "elapsed": 0.025553,
      "return_value": {
        "class": "String",
        "value": "YWRtaW46YmRjYzUxODQtOTZhYi00Y2JmLWIyNzctYTBlYzAxZjhmYjI3",
        "object_id": 70146523040500
      }
    },
    {
      "id": 26715,
      "event": "call",
      "thread_id": 70146500788180,
      "defined_class": "JSON::Ext::Generator::State",
      "method_id": "generate",
      "path": "JSON::Ext::Generator::State#generate",
      "static": false,
      "parameters": [
        {
          "name": "arg",
          "class": "Hash",
          "object_id": 70146523088260,
          "value": "{\"api_key\"=>\"YWRtaW46YmRjYzUxODQtOTZhYi00Y2JmLWIyNzctYTBlYzAxZjhmYjI3\"}",
          "kind": "req"
        }
      ],
      "receiver": {
        "class": "JSON::Ext::Generator::State",
        "object_id": 70146523088020,
        "value": "#<JSON::Ext::Generator::State:0x00007f98852e8928>"
      }
    },
    {
      "id": 26716,
      "event": "return",
      "thread_id": 70146500788180,
      "parent_id": 26715,
      "elapsed": 0.000026,
      "return_value": {
        "class": "String",
        "value": "{\"api_key\":\"YWRtaW46YmRjYzUxODQtOTZhYi00Y2JmLWIyNzctYTBlYzAxZjhmYjI3\"}",
        "object_id": 70146236898180
      }
    },
    {
      "id": 26717,
      "event": "return",
      "thread_id": 70146500788180,
      "parent_id": 26708,
      "elapsed": 0.026007,
      "return_value": {
        "class": "String",
        "value": "{\"api_key\":\"YWRtaW46YmRjYzUxODQtOTZhYi00Y2JmLWIyNzctYTBlYzAxZjhmYjI3\"}",
        "object_id": 70146236898180
      }
    },
    {
      "id": 26718,
      "event": "return",
      "thread_id": 70146500788180,
      "parent_id": 26693,
      "elapsed": 0.048602,
      "http_server_response": {
        "status": 201,
        "mime_type": "application/json; charset=utf-8"
      }
    },
    {
      "id": 26719,
      "event": "call",
      "thread_id": 70146500788180,
      "defined_class": "JSON::Ext::Parser",
      "method_id": "parse",
      "path": "JSON::Ext::Parser#parse",
      "static": false,
      "parameters": [],
      "receiver": {
        "class": "JSON::Ext::Parser",
        "object_id": 70146232352900,
        "value": "#<JSON::Ext::Parser:0x00007f9862860108>"
      }
    },
    {
      "id": 26720,
      "event": "return",
      "thread_id": 70146500788180,
      "parent_id": 26719,
      "elapsed": 0.000011,
      "return_value": {
        "class": "Hash",
        "value": "{\"api_key\"=>\"YWRtaW46YmRjYzUxODQtOTZhYi00Y2JmLWIyNzctYTBlYzAxZjhmYjI3\"}",
        "object_id": 70146232419800
      }
    }
  ]
}