]> git.immae.eu Git - github/bastienwirtz/homer.git/commitdiff
Merge branch 'bastienwirtz:main' into hotkey
authorRobin Schneider <45321827+robinschneider@users.noreply.github.com>
Sun, 10 Oct 2021 19:40:42 +0000 (21:40 +0200)
committerGitHub <noreply@github.com>
Sun, 10 Oct 2021 19:40:42 +0000 (21:40 +0200)
.github/PULL_REQUEST_TEMPLATE.md
.github/workflows/integration.yml [new file with mode: 0644]
.github/workflows/release.yml [moved from .github/workflows/main.yml with 100% similarity]
docs/configuration.md
docs/customservices.md
src/App.vue
src/assets/defaults.yml
src/components/Service.vue
src/components/services/AdGuardHome.vue
src/components/services/Ping.vue
src/mixins/service.js [new file with mode: 0644]

index 07468630522add9917c2344585a94095f80c88e8..e0063d580ee74a5053a31a67bd9ee8419e520a97 100644 (file)
@@ -14,5 +14,5 @@ Fixes # (issue)
 
 - [ ] I've read & comply with the [contributing guidelines](https://github.com/bastienwirtz/homer/blob/main/CONTRIBUTING.md)
 - [ ] I have tested my code for new features & regressions on both mobile & desktop devices, using the latest version of major browsers. 
-- [ ] I have made corresponding changes the documentation (README.md).
+- [ ] I have made corresponding changes to the documentation (README.md).
 - [ ] I've checked my modifications for any breaking changes, especially in the `config.yml` file
diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml
new file mode 100644 (file)
index 0000000..196113d
--- /dev/null
@@ -0,0 +1,31 @@
+# This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node
+# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
+
+name: Node.js CI
+
+on:
+  push:
+    branches: [ main ]
+  pull_request:
+    branches: [ main ]
+
+jobs:
+  build:
+
+    runs-on: ubuntu-latest
+
+    strategy:
+      matrix:
+        node-version: [16.x]
+        # See supported Node.js release schedule at https://nodejs.org/en/about/releases/
+
+    steps:
+    - uses: actions/checkout@v2
+    - name: Use Node.js ${{ matrix.node-version }}
+      uses: actions/setup-node@v2
+      with:
+        node-version: ${{ matrix.node-version }}
+        cache: 'yarn'
+    - run: yarn install
+    - run: yarn lint
+
index 807fa688559d7251b35fb8d34f39e3e219986300..c554297362b2fb836dfb7d12277a18e4a79fb09c 100644 (file)
@@ -26,6 +26,11 @@ footer: '<p>Created with <span class="has-text-danger">❤️</span> with <a hre
 columns: "3" # "auto" or number (must be a factor of 12: 1, 2, 3, 4, 6, 12)
 connectivityCheck: true # whether you want to display a message when the apps are not accessible anymore (VPN disconnected for example)
 
+# Optional: Proxy / hosting option
+proxy:
+  # NOT All custom services implements this new option YET. Support will be extended very soon.
+  useCredentials: false # send cookies & authorization headers when fetching service specific data. Set to `true` if you use an authentication proxy. Can be overrided on service level. 
+
 # Optional theming
 theme: default # 'default' or one of the themes available in 'src/assets/themes'.
 
index f79428fc7afa6898f1aee579ecf2982a39583622..ef8494893b730979b92c62446518f0c484573afe 100644 (file)
@@ -6,6 +6,20 @@ within Homer.
 
 If you experiencing any issue, please have a look to the [troubleshooting](troubleshooting.md) page.
 
+
+## Common options
+
+```yaml
+- name: "My Service"
+  logo: "assets/tools/sample.png"
+  url: "http://my-service-link"
+  endpoint: "http://my-service-endpoint" # Optional: alternative base URL used to fetch service data is necessary.
+  useCredentials: false # Optional: Override global proxy.useCredentials configuration.
+  type: "<type>"
+```
+
+⚠️🚧 `endpoint` & `useCredentials` new options are not yet supported by all custom services (but will be very soon).
+
 ## PiHole
 
 Using the PiHole service you can display info about your local PiHole instance right on your Homer dashboard.
@@ -13,12 +27,11 @@ Using the PiHole service you can display info about your local PiHole instance r
 The following configuration is available for the PiHole service.
 
 ```yaml
- items:
-      - name: "Pi-hole"
-        logo: "assets/tools/sample.png"
-        # subtitle: "Network-wide Ad Blocking" # optional, if no subtitle is defined, PiHole statistics will be shown
-        url: "http://192.168.0.151/admin"
-        type: "PiHole"
+- name: "Pi-hole"
+  logo: "assets/tools/sample.png"
+  # subtitle: "Network-wide Ad Blocking" # optional, if no subtitle is defined, PiHole statistics will be shown
+  url: "http://192.168.0.151/admin"
+  type: "PiHole"
 ```
 
 ## OpenWeatherMap
@@ -27,14 +40,13 @@ Using the OpenWeatherMap service you can display weather information about a giv
 The following configuration is available for the OpenWeatherMap service:
 
 ```yaml
-items:
-     - name: "Weather"
-       location: "Amsterdam" # your location.
-       locationId: "2759794" # Optional: Specify OpenWeatherMap city ID for better accuracy
-       apiKey: "<---insert-api-key-here--->" # insert your own API key here. Request one from https://openweathermap.org/api.
-       units: "metric" # units to display temperature. Can be one of: metric, imperial, kelvin. Defaults to kelvin.
-       background: "square" # choose which type of background you want behind the image. Can be one of: square, cicle, none. Defaults to none.
-       type: "OpenWeather"
+- name: "Weather"
+  location: "Amsterdam" # your location.
+  locationId: "2759794" # Optional: Specify OpenWeatherMap city ID for better accuracy
+  apiKey: "<---insert-api-key-here--->" # insert your own API key here. Request one from https://openweathermap.org/api.
+  units: "metric" # units to display temperature. Can be one of: metric, imperial, kelvin. Defaults to kelvin.
+  background: "square" # choose which type of background you want behind the image. Can be one of: square, cicle, none. Defaults to none.
+  type: "OpenWeather"
 ```
 
 **Remarks:**
@@ -46,8 +58,8 @@ This service displays News (grey), Warning (orange) or Error (red) notifications
 Two lines are needed in the config.yml :
 
 ```yaml
-type: "Medusa"
-apikey: "01234deb70424befb1f4ef6a23456789"
+  type: "Medusa"
+  apikey: "01234deb70424befb1f4ef6a23456789"
 ```
 
 The url must be the root url of Medusa application.
@@ -59,8 +71,8 @@ This service displays Activity (blue), Warning (orange) or Error (red) notificat
 Two lines are needed in the config.yml :
 
 ```yaml
-type: "Radarr" or "Sonarr"
-apikey: "01234deb70424befb1f4ef6a23456789"
+  type: "Radarr" or "Sonarr"
+  apikey: "01234deb70424befb1f4ef6a23456789"
 ```
 
 The url must be the root url of Radarr/Sonarr application.
@@ -75,10 +87,9 @@ For Paperless you need an API-Key which you have to store at the item in the fie
 For Ping you need to set the type to Ping and provide a url.
 
 ```yaml
-items:
-   - name: "Awesome app"
-     type: Ping
-     logo: "assets/tools/sample.png"
-     subtitle: "Bookmark example" tag: "app" 
-     url: "https://www.reddit.com/r/selfhosted/" 
+- name: "Awesome app"
+  type: Ping
+  logo: "assets/tools/sample.png"
+  subtitle: "Bookmark example" tag: "app" 
+  url: "https://www.reddit.com/r/selfhosted/" 
 ```
index 9b4803f2d04005e1092c3846ee9baa68998f8acf..5e717969137e0e0a0c94010f7f800bb6f027d226 100644 (file)
@@ -75,7 +75,8 @@
               <Service
                 v-for="(item, index) in group.items"
                 :key="index"
-                v-bind:item="item"
+                :item="item"
+                :proxy="config.proxy"
                 :class="['column', `is-${12 / config.columns}`]"
               />
             </template>
               <Service
                 v-for="(item, index) in group.items"
                 :key="index"
-                v-bind:item="item"
+                :item="item"
+                :proxy="config.proxy"
               />
             </div>
           </div>
index f011346cf174724e730517dff5d589fada0cc628..ae4f52367fa5f3a88b446c9e1cf7c0496cc54a50 100644 (file)
@@ -42,3 +42,6 @@ colors:
 message: ~
 links: []
 services: []
+
+
+proxy: ~
\ No newline at end of file
index 39a9ac41e0df81855e4970f012d775eb2b09a398..25b86d5f9e685924b2dcf2bdd7b251547ed045fd 100644 (file)
@@ -1,5 +1,5 @@
 <template>
-  <component v-bind:is="component" :item="item"></component>
+  <component v-bind:is="component" :item="item" :proxy="proxy"></component>
 </template>
 
 <script>
@@ -9,6 +9,7 @@ export default {
   name: "Service",
   props: {
     item: Object,
+    proxy: Object,
   },
   computed: {
     component() {
index 16881fa59ea6d93ceb43bd4573e785fb1107cce1..b01f0f49a56c9f262bfc45d8409e0ae8fe464ec3 100644 (file)
 </template>
 
 <script>
+import service from "@/mixins/service.js";
 import Generic from "./Generic.vue";
 
 export default {
   name: "AdGuardHome",
+  mixins: [service],
   props: {
     item: Object,
   },
@@ -60,18 +62,14 @@ export default {
   },
   methods: {
     fetchStatus: async function () {
-      this.status = await fetch(`${this.item.url}/control/status`, {
-        credentials: "include",
-      })
-        .then((response) => response.json())
-        .catch((e) => console.log(e));
+      this.status = await this.fetch("/control/status").catch((e) =>
+        console.log(e)
+      );
     },
     fetchStats: async function () {
-      this.stats = await fetch(`${this.item.url}/control/stats`, {
-        credentials: "include",
-      })
-        .then((response) => response.json())
-        .catch((e) => console.log(e));
+      this.stats = await this.fetch("/control/stats").catch((e) =>
+        console.log(e)
+      );
     },
   },
 };
index 6fd3ec57f987e34719e7b169f5adaa16ab604303..d1fda576eff412d964739c58d8e16a3ae0b11253 100644 (file)
@@ -9,10 +9,12 @@
 </template>
 
 <script>
+import service from "@/mixins/service.js";
 import Generic from "./Generic.vue";
 
 export default {
   name: "Ping",
+  mixins: [service],
   props: {
     item: Object,
   },
@@ -27,16 +29,8 @@ export default {
   },
   methods: {
     fetchStatus: async function () {
-      const url = `${this.item.url}`;
-      fetch(url, {
-        method: "HEAD",
-        cache: "no-cache",
-        credentials: "include",
-      })
-        .then((response) => {
-          if (!response.ok) {
-            throw Error(response.statusText);
-          }
+      this.fetch("/", { method: "HEAD", cache: "no-cache" }, false)
+        .then(() => {
           this.status = "online";
         })
         .catch(() => {
diff --git a/src/mixins/service.js b/src/mixins/service.js
new file mode 100644 (file)
index 0000000..17fa6fc
--- /dev/null
@@ -0,0 +1,43 @@
+export default {
+  props: {
+    proxy: Object,
+  },
+  created: function () {
+    // custom service often consume info from an API using the item link (url) as a base url,
+    // but sometimes the base url is different. An optional alternative URL can be provided with the "endpoint" key.
+    this.endpoint = this.item.endpoint || this.item.url;
+
+    if (this.endpoint.endsWith("/")) {
+      this.endpoint = this.endpoint.slice(0, -1);
+    }
+  },
+  methods: {
+    fetch: function (path, init, json = true) {
+      let options = {};
+
+      if (this.proxy?.useCredentials) {
+        options.credentials = "include";
+      }
+
+      // Each item can override the credential settings
+      if (this.item.useCredentials !== undefined) {
+        options.credentials =
+          this.item.useCredentials === true ? "include" : "omit";
+      }
+
+      options = Object.assign(options, init);
+
+      if (path.startsWith("/")) {
+        path = path.slice(1);
+      }
+
+      return fetch(`${this.endpoint}/${path}`, options).then((response) => {
+        if (!response.ok) {
+          throw new Error("Not 2xx response");
+        }
+
+        return json ? response.json() : response;
+      });
+    },
+  },
+};