@frigear-nu/oauth-server 0.1.3 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@frigear-nu/oauth-server",
3
3
  "configKey": "oauthServer",
4
- "version": "0.1.3",
4
+ "version": "0.2.1",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.3",
7
7
  "unbuild": "unknown"
@@ -1,6 +1,7 @@
1
1
  <script setup>
2
2
  import * as z from "zod";
3
3
  import { isNativeRedirectUri, isSecureOrigin } from "../../utils";
4
+ import { computed, reactive, useAction, useModuleT } from "#imports";
4
5
  defineOptions({ name: "OAuthApplicationSlideover" });
5
6
  const props = defineProps({
6
7
  application: { type: Object, required: false },
@@ -1,4 +1,5 @@
1
1
  <script setup>
2
+ import { useCopyToClipboard, useModuleT } from "#imports";
2
3
  defineOptions({ name: "OAuthCredentialsModal" });
3
4
  defineProps({
4
5
  name: { type: String, required: true },
@@ -1,6 +1,7 @@
1
1
  import OAuthApplicationSlideover from "../components/OAuthApplicationSlideover.vue";
2
2
  import OAuthCredentialsModal from "../components/OAuthCredentialsModal.vue";
3
3
  import { OAUTH_APPLICATIONS_KEY, oauthApplicationsApi } from "./useOAuthApplications.js";
4
+ import { ref, refreshNuxtData, useAction, useConfirmDialog, useCopyToClipboard, useModuleT, useOverlay, useRoute, useRouter, useToast } from "#imports";
4
5
  export function useOAuthApplicationActions() {
5
6
  const t = useModuleT("oauthServer");
6
7
  const overlay = useOverlay();
@@ -1,5 +1,7 @@
1
- import type { MaybeRefOrGetter } from 'vue';
2
- import type { AdminApplicationDto, ApplicationInput, CreatedApplicationDto } from '../../../types.js';
1
+ import type { ComputedRef, MaybeRefOrGetter } from 'vue';
2
+ import type { AsyncData, NuxtError } from 'nuxt/app';
3
+ import type { AdminApplicationDto, AdminApplicationsPage, ApplicationInput, CreatedApplicationDto } from '../../../types.js';
4
+ type Application = AdminApplicationDto;
3
5
  /** The `useFetch` key of the admin list; `refreshNuxtData(OAUTH_APPLICATIONS_KEY)` reloads it from anywhere. */
4
6
  export declare const OAUTH_APPLICATIONS_KEY = "oauth-server:applications";
5
7
  /** The admin endpoints as plain calls (no refresh). Every call needs the host's `oauth:authorize` hook to allow the user. */
@@ -16,15 +18,33 @@ export declare const oauthApplicationsApi: {
16
18
  };
17
19
  /** The list query: `page`, `pageSize`, `q` (name or client id), `sort` (`createdAt`, `name`, `priority`) and `order`. */
18
20
  export type OAuthApplicationsQuery = Record<string, string | number | undefined>;
21
+ type ApplicationsAsyncData = Awaited<AsyncData<AdminApplicationsPage | undefined, NuxtError | undefined>>;
22
+ /** What `useOAuthApplications` returns (and resolves with when awaited). */
23
+ export interface OAuthApplicationsState {
24
+ applications: ComputedRef<Application[]>;
25
+ total: ComputedRef<number>;
26
+ data: ApplicationsAsyncData['data'];
27
+ status: ApplicationsAsyncData['status'];
28
+ error: ApplicationsAsyncData['error'];
29
+ loading: ComputedRef<boolean>;
30
+ refreshing: ComputedRef<boolean>;
31
+ refresh: ApplicationsAsyncData['refresh'];
32
+ create: (input: ApplicationInput) => Promise<CreatedApplicationDto>;
33
+ update: (id: string, patch: Partial<ApplicationInput>) => Promise<Application>;
34
+ remove: (id: string) => Promise<null>;
35
+ rotateSecret: (id: string) => Promise<string>;
36
+ revokeGrants: (id: string) => Promise<Application>;
37
+ }
19
38
  /**
20
39
  * Admin CRUD for applications, with one page of the list. Awaitable: `await useOAuthApplications(query)` in a page
21
40
  * renders the list on the server; pass `useTableQuery().query` to page, search and sort it. `applications` is `[]`
22
41
  * until loaded and after an error: check `loading` and `error` first. Every call needs the host's `oauth:authorize`
23
42
  * hook to allow the user.
24
43
  */
25
- export declare function useOAuthApplications(query?: MaybeRefOrGetter<OAuthApplicationsQuery>): any;
44
+ export declare function useOAuthApplications(query?: MaybeRefOrGetter<OAuthApplicationsQuery>): OAuthApplicationsState & Promise<OAuthApplicationsState>;
26
45
  /**
27
46
  * The applications the signed-in user may sign in to. Awaitable: `await useMyApplications()` in a page renders them on
28
47
  * the server. `applications` is `[]` until loaded and after an error: check `loading` and `error` first.
29
48
  */
30
49
  export declare function useMyApplications(): any;
50
+ export {};
@@ -1,4 +1,5 @@
1
1
  import { oauthServerApi } from "../../utils/api.js";
2
+ import { $fetch, computed, useCachedFetch, useFetch, useUserSession, watch } from "#imports";
2
3
  export const OAUTH_APPLICATIONS_KEY = "oauth-server:applications";
3
4
  export const oauthApplicationsApi = {
4
5
  get: (id) => $fetch(oauthServerApi.admin.application(id)),
@@ -1,5 +1,6 @@
1
1
  <script setup>
2
2
  import { oauthApplicationsApi } from "../composables/useOAuthApplications";
3
+ import { computed, numericColumn, onMounted, useModuleT, useOAuthApplicationActions, useOAuthApplications, useRoute, useTableQuery, useTableSort, watch } from "#imports";
3
4
  defineOptions({ name: "OAuthAdminPage" });
4
5
  const t = useModuleT("oauthServer");
5
6
  const route = useRoute();
@@ -1,4 +1,5 @@
1
1
  <script setup>
2
+ import { useModuleT, useMyApplications } from "#imports";
2
3
  defineOptions({ name: "OAuthApplicationsPage" });
3
4
  const t = useModuleT("oauthServer");
4
5
  const { applications, loading, error, refresh } = await useMyApplications();
@@ -1,5 +1,7 @@
1
1
  <script setup>
2
+ import { isNativeRedirectUri } from "../../utils";
2
3
  import { oauthServerApi, oidc } from "../../utils/api";
4
+ import { $fetch, navigateTo, ref, useAuthPages, useErrorToast, useFetch, useModuleT, useRoute } from "#imports";
3
5
  defineOptions({ name: "OAuthAuthorizePage" });
4
6
  const t = useModuleT("oauthServer");
5
7
  const route = useRoute();
@@ -21,6 +23,7 @@ const scopeLabel = (scope) => {
21
23
  return known[scope] ?? scope;
22
24
  };
23
25
  const pending = ref(null);
26
+ const appRedirectUrl = ref(null);
24
27
  async function decide(approved) {
25
28
  pending.value = approved ? "approve" : "deny";
26
29
  try {
@@ -28,6 +31,12 @@ async function decide(approved) {
28
31
  method: "POST",
29
32
  body: { ...route.query, approved }
30
33
  });
34
+ if (isNativeRedirectUri(redirectUrl)) {
35
+ appRedirectUrl.value = redirectUrl;
36
+ pending.value = null;
37
+ window.location.href = redirectUrl;
38
+ return;
39
+ }
31
40
  await navigateTo(redirectUrl, { external: true });
32
41
  } catch (err) {
33
42
  showError(err, t("authorize.failed", "Could not complete the sign-in. Please try again."));
@@ -38,7 +47,22 @@ async function decide(approved) {
38
47
 
39
48
  <template>
40
49
  <AuthCard
41
- v-if="consent"
50
+ v-if="consent && appRedirectUrl"
51
+ :title="t('authorize.returnTitle', 'Return to {name}', { name: consent.application.name })"
52
+ :description="t('authorize.returnHint', 'If the app did not open, tap the button below. You can close this window afterwards.')"
53
+ >
54
+ <UButton
55
+ :to="appRedirectUrl"
56
+ external
57
+ block
58
+ size="lg"
59
+ icon="i-lucide-external-link"
60
+ :label="t('authorize.returnToApp', 'Return to the app')"
61
+ />
62
+ </AuthCard>
63
+
64
+ <AuthCard
65
+ v-else-if="consent"
42
66
  :title="t('authorize.title', 'Sign in to {name}', { name: consent.application.name })"
43
67
  >
44
68
  <template #description>
@@ -109,6 +109,9 @@
109
109
  "invalidTitle": "Denne loginanmodning kan ikke gennemføres",
110
110
  "invalidDescription": "Anmodningen er ugyldig.",
111
111
  "failed": "Login kunne ikke gennemføres. Prøv igen.",
112
+ "returnTitle": "Vend tilbage til {name}",
113
+ "returnToApp": "Vend tilbage til appen",
114
+ "returnHint": "Hvis appen ikke åbnede, så tryk på knappen nedenfor. Du kan lukke dette vindue bagefter.",
112
115
  "scope": {
113
116
  "openid": "Bekræfte din identitet",
114
117
  "profile": "Dit navn og profilbillede",
@@ -109,6 +109,9 @@
109
109
  "invalidTitle": "This sign-in request cannot be completed",
110
110
  "invalidDescription": "The request is invalid.",
111
111
  "failed": "Could not complete the sign-in. Please try again.",
112
+ "returnTitle": "Return to {name}",
113
+ "returnToApp": "Return to the app",
114
+ "returnHint": "If the app did not open, tap the button below. You can close this window afterwards.",
112
115
  "scope": {
113
116
  "openid": "Verify your identity",
114
117
  "profile": "Your name and profile picture",
@@ -1,4 +1,5 @@
1
1
  import { defineMenuItem, defineMenuSource, extendMenuItem } from "@frigear-nu/menu/utils";
2
+ import { useRuntimeConfig } from "#imports";
2
3
  export default defineMenuSource(() => {
3
4
  const config = useRuntimeConfig().public.oauthServer;
4
5
  if (config?.pages?.applications) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frigear-nu/oauth-server",
3
- "version": "0.1.3",
3
+ "version": "0.2.1",
4
4
  "description": "OAuth 2.0 / OpenID Connect server for the frigear ecosystem: register applications that users with certain roles may sign in to.",
5
5
  "url": "https://docs.frigear.dev/modules/oauth-server",
6
6
  "author": {
@@ -42,12 +42,12 @@
42
42
  "playground"
43
43
  ],
44
44
  "dependencies": {
45
- "@frigear-nu/admin": "0.1.3",
46
- "@frigear-nu/module-kit": "1.1.3",
47
- "@frigear-nu/ui": "0.1.3",
48
- "@frigear-nu/auth": "0.1.4",
49
- "@frigear-nu/mcp": "0.1.3",
50
- "@frigear-nu/users": "1.1.4",
45
+ "@frigear-nu/admin": "0.2.0",
46
+ "@frigear-nu/module-kit": "1.2.0",
47
+ "@frigear-nu/ui": "0.2.0",
48
+ "@frigear-nu/auth": "0.2.0",
49
+ "@frigear-nu/mcp": "0.2.0",
50
+ "@frigear-nu/users": "1.2.0",
51
51
  "@libsql/client": "^0.18.0",
52
52
  "@nuxt/kit": "^4.6.1",
53
53
  "drizzle-kit": "^0.31.11",
@@ -57,7 +57,7 @@
57
57
  "zod": "^4.6.5"
58
58
  },
59
59
  "peerDependencies": {
60
- "@frigear-nu/menu": "0.1.3",
60
+ "@frigear-nu/menu": "0.2.0",
61
61
  "@nuxt/ui": "^4.12.0",
62
62
  "@nuxthub/core": "^0.10.8"
63
63
  },
@@ -70,7 +70,7 @@
70
70
  }
71
71
  },
72
72
  "devDependencies": {
73
- "@frigear-nu/menu": "0.1.3",
73
+ "@frigear-nu/menu": "0.2.0",
74
74
  "@nuxt/devtools": "^3.4.2",
75
75
  "@nuxt/eslint-config": "^1.17.0",
76
76
  "@nuxt/module-builder": "^1.0.3",