{"id":13829788,"url":"https://github.com/yogthos/memory-hole","last_synced_at":"2025-04-09T20:11:23.859Z","repository":{"id":87797918,"uuid":"65673654","full_name":"yogthos/memory-hole","owner":"yogthos","description":"Memory Hole is a support issue organizer application","archived":false,"fork":false,"pushed_at":"2020-05-30T16:05:43.000Z","size":2036,"stargazers_count":264,"open_issues_count":5,"forks_count":24,"subscribers_count":20,"default_branch":"master","last_synced_at":"2025-04-09T20:10:59.887Z","etag":null,"topics":["collaboration","issue-tracker","notes","organizer","team","web-app"],"latest_commit_sha":null,"homepage":"","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yogthos.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"yogthos"}},"created_at":"2016-08-14T15:43:19.000Z","updated_at":"2025-02-22T21:32:44.000Z","dependencies_parsed_at":null,"dependency_job_id":"79b22d6b-50f2-4ee0-9fdd-acdeb6b0ccec","html_url":"https://github.com/yogthos/memory-hole","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yogthos%2Fmemory-hole","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yogthos%2Fmemory-hole/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yogthos%2Fmemory-hole/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yogthos%2Fmemory-hole/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yogthos","download_url":"https://codeload.github.com/yogthos/memory-hole/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248103872,"owners_count":21048245,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["collaboration","issue-tracker","notes","organizer","team","web-app"],"created_at":"2024-08-04T10:00:45.672Z","updated_at":"2025-04-09T20:11:23.827Z","avatar_url":"https://github.com/yogthos.png","language":"Clojure","funding_links":["https://github.com/sponsors/yogthos"],"categories":["Examples"],"sub_categories":["Web"],"readme":"# Memory Hole\n\n\u003cimg src=\"https://cdn.rawgit.com/yogthos/memory-hole/master/memory-hole.png\"\n hspace=\"20\" align=\"left\" height=\"200\"/\u003e\n\n\u003eWhen one knew that any document was due for destruction, or even when one saw a scrap of waste paper lying about, it was an automatic action to lift the flap of the nearest memory hole and drop it in, whereupon it would be whirled away on a current of warm air to the enormous furnaces which were hidden somewhere in the recesses of the building\n\u003e- from [1984 by George Orwell](https://www.goodreads.com/book/show/5470.1984)\n\n---\n\nMemory Hole is a support issue organizer. It's designed to provide a way to organize and search common support issues and their resolution.\n\n### [screenshots](https://github.com/yogthos/memory-hole/tree/master/screenshots)\n\n## 1.0 Features\n\n- The app uses LDAP and/or internal table to handle authentication\n- Issues are ranked based on the number of views and last time of access\n- File attachments for issues\n- Issues are organized by user generated tags\n- Markdown with live preview for issues\n- Weighted full text search using PostgreSQL citext extension\n- Users can view/edit issues based on their group membership\n- If using LDAP, issues can be assigned to LDAP groups\n- LDAP groups can be aliased with user friendly names\n\n## Prerequisites\n\nYou will need the following to compile and run the application:\n\n* [JDK](http://www.azul.com/downloads/zulu)\n* [Leiningen](https://leiningen.org/)\n* [PostgreSQL](http://postgresql.org) - see [here](#configuring-postgresql) for configuration details\n\n## Running with Docker\n\n```\nmkdir memory-hole\ncd memory-hole\ncurl -O https://raw.githubusercontent.com/yogthos/memory-hole/master/docker-compose.yml\ndocker-compose up\n```\n\nThe app will be available at `http://localhost:8000` once it starts.\n\n## Configuring the database\n\n### PostgreSQL\n\nFollow these steps to configure the database for the application:\n\n0. Make sure you have the [CITEXT](https://www.postgresql.org/docs/9.5/static/citext.html)\nextension installed on PostgreSQL.\n\n1. Run the `psql` command:\n\n        psql -U \u003csuperuser|postgres user\u003e -d postgres -h localhost\n\n2. Create the role role for accessing the database:\n\n        CREATE ROLE memoryhole;\n\n3. Set the password for the role:\n\n        \\password memoryhole;\n\n4. Optionally, create a schema and grant the `memoryhole` role authorization:\n\n        CREATE SCHEMA memoryhole AUTHORIZATION memoryhole;\n        GRANT ALL ON SCHEMA memoryhole TO memoryhole;\n        GRANT ALL ON ALL TABLES IN SCHEMA memoryhole TO memoryhole;\n\n5. Add the CITEXT extension to the schema:\n\n        CREATE EXTENSION IF NOT EXISTS citext WITH SCHEMA memoryhole;\n\n6. Make sure memoryhole is allowed to login:\n\n        ALTER ROLE \"memoryhole\" WITH LOGIN;\n\n7. Exit the shell\n\n        \\q\n\nThis setup should lead to similar `:database-url` (eg. on local machine).\n\n```clojure\n:database-url \"jdbc:postgresql://localhost/postgres?user=memoryhole\u0026password=memoryhole\"\n```\n\n### H2\n\nH2 DB can use various hosting scenarios, which are available on its [feature list](http://h2database.com/html/features.html).\n\nThis setup can lead to following `:database-url` on local machine.\n\n```clojure\n:database-url \"jdbc:h2:~/memory-hole-dev\"\n```\n\nWhen H2 DB is used for development or production, it needs to have properly set migratus `:migration-dir` pointing to H2 specific migrations for populating schema.\n\n```clojure\n:migration-dir \"migrations/h2\"\n```\n\n## Running during development\n\nCreate a `profiles.clj` file in the project directory with the configuration settings for the database. Optionally migrations directory and LDAP can be configured, e.g:\n\n```clojure\n{:profiles/dev\n {:env\n  {:database-url \"jdbc:postgresql://localhost/postgres?user=memoryhole\u0026password=memoryhole\"\n  :migration-dir \"migrations/postgresql\"\n  ;;ldap is optional, will use internal table otherwise\n  ;;Admin users (able to manage groups) defined by their sAMAccountName\n  :ldap-admin-users [\"my-ldap-sAMAccountName\" \"another-ldap-sAMAccountName\"]\n  ;;Or Admin Groups defined by their distinguished names\n  :ldap-admin-groups [\"CN=some-ldap-group,OU=foo123,DC=domain,DC=ca\"]\n  :ldap\n  {:host\n     {:address         \"my-ldap-server.ca\"\n      :domain          \"domain.ca\"\n      :port            389\n      :connect-timeout (* 1000 5)\n      :timeout         (* 1000 30)}}}}}\n```\n\nRun the migrations\n\n    lein run migrate\n\nThis will create the tables and add a default admin user, The default login is: `admin/admin`.\n\nTo start a web server for the application, run:\n\n    lein run\n\nTo compile ClojureScript front-end, run:\n\n    lein figwheel\n\n## Building for production\n\n    lein uberjar\n\nThis will produce `target/uberjar/memory-hole.jar` archive that can be run as follows:\n\n    java -Dconf=conf.edn -jar memory-hole.jar migrate\n    java -Dconf=conf.edn -jar memory-hole.jar\n\nThe `conf.edn` file should contain the configuration such as the database URL that will be used in production. The following options are available.\n\n### Database URL\n\n```clojure\n:database-url \"jdbc:postgresql://localhost/postgres?user=memoryhole\u0026password=memoryhole\"\n```\n\n### Migration directory\n\nDepending on selected DB backend, migration directory needs to be set, eg.\n\n```clojure\n:migration-dir \"migrations/postgresql\"\n```\n\n### HTTP Port\n\nThe HTTP port defaults to `3000`, to set a custom port add the following key to the config:\n\n```clojure\n:port 80\n```\n\n### Session Configuration\n\nThe app defaults to using a server-side memory based session store.\n\nThe number of sessions before a memory session times out can be set using the `:memory-session` key as follows:\n\n```clojure\n:memory-session\n{:max-age 3600}\n```\n\nIf you wish to use a cookie based memory store, then add a `:cookie-session` key to the configuration.\nThe `:cookie-session` key should point to a map containing two optional key:\n\n* `:key` - a secret key used to encrypt the session cookie\n* `:cookie-attrs` - a map containing optional cookie attributes:\n* `:http-only` - restrict the cookie to HTTP if true (default)\n* `:secure` - restrict the cookie to HTTPS URLs if true\n* `:max-age` - the number of seconds until the cookie expires\n\nAn example configuration might look as follows:\n\n```clojure\n:cookie-session\n{:key \"a 16-byte secret\"\n :cookie-attrs\n {:secure  true\n  :max-age 3600}}\n```\n\n### LDAP Support\n\nThe LDAP connection configuration should be placed under the `:ldap` key as follows:\n\n```clojure\n:ldap\n  {:host\n     {:address         \"my-ldap-server.ca\"\n      :domain          \"domain.ca\"\n      :port            389\n      :connect-timeout (* 1000 5)\n      :timeout         (* 1000 30)}}\n```\n\nThere are two options for managing user groups when using LDAP, you can either assign\nadmin users using the `sAMAccountName`, or specify groups that correspond to the `memberOf` key.\n\n```clojure\n:ldap-admin-users [\"my-ldap-sAMAccountName\" \"another-ldap-sAMAccountName\"]\n```\n\n```clojure\n:ldap-admin-groups [\"CN=some-ldap-group,OU=foo123,DC=domain,DC=ca\"]\n```\n\n### HTTPS Support\n\nTo enable HTTPS support in production add the the following configuration under the `:ssl` key:\n\n```clojure\n:ssl\n{:port 3001\n :keystore \"keystore.jks\"\n :keystore-pass \"changeit\"}\n```\n\nTo disable HTTP access, set the `:port` to `nil`:\n\n```clojure\n:port nil\n```\n\nAlternatively, you can front the app with Nginx in production.\nSee [here](http://www.luminusweb.net/docs/deployment.md#setting_up_ssl) for details on configuring Nginx.\n\nA complete `conf.edn` example:\n\n```clojure\n{:database-url \"jdbc:postgresql://localhost/postgres?user=memoryhole\u0026password=memoryhole\"\n :cookie-session\n {:key \"a 16-byte secret\"\n  :cookie-attrs\n  {:max-age 60}}\n :port nil\n :ssl\n {:port 3001\n  :keystore \"keystore.jks\"\n  :keystore-pass \"changeit\"}}\n```\n\n## Nginx Proxy\n\nThe app can be proxied with Nginx to a custom path as follows:\n\n```\nserver {\n    listen ...;\n    ...\n    location /memory-hole {\n        proxy_pass http://127.0.0.1:3000;\n    }\n    ...\n}\n```\n\nYou will then need to add the `:app-context` in the `conf.edn` file with the context:\n\n```clojure\n{:database-url \"jdbc:postgresql://localhost/postgres?user=memoryhole\u0026password=memoryhole\"\n :port 3000\n :app-context \"/memory-hole\"}\n```\n\n\n## Acknowledgments\n\nThe original implementation of the tool was written by [Ryan Baldwin](https://github.com/ryanbaldwin). The app is based on the original schema and SQL queries.\n\n## License\n\nCopyright © 2016 Dmitri Sotnikov\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyogthos%2Fmemory-hole","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyogthos%2Fmemory-hole","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyogthos%2Fmemory-hole/lists"}