feat: Passwordless cross-device authentication

- Arkitektur: docs/auth/passwordless-architecture.md
- Backend: iom/quixzoom-auth-service/ (FastAPI + Redis)
- Webb: quixzoom-market-pages/se/login/ (QR-kod + polling)
- App: iom/quixzoom-app/src/features/auth/ (push + deep links)

Flöde: QR-kod → app-godkännande → webb-inloggad
This commit is contained in:
Bernt
2026-07-07 07:11:50 +00:00
parent 4aa984ad74
commit 6989a98d75
61843 changed files with 5491611 additions and 872231 deletions
+21
View File
@@ -0,0 +1,21 @@
import { GetQueues } from '../../@types/api';
import { SelectedStatuses } from '../../@types/app';
export declare class Api {
private axios;
constructor({ basePath }?: {
basePath: string;
});
getQueues({ status, }: {
status: SelectedStatuses;
}): Promise<GetQueues>;
retryAll(queueName: string): Promise<void>;
cleanAllDelayed(queueName: string): Promise<void>;
cleanAllFailed(queueName: string): Promise<void>;
cleanAllCompleted(queueName: string): Promise<void>;
cleanJob(queueName: string, jobId: string | number | undefined): Promise<void>;
retryJob(queueName: string, jobId: string | number | undefined): Promise<void>;
promoteJob(queueName: string, jobId: string | number | undefined): Promise<void>;
getJobLogs(queueName: string, jobId: string | number | undefined): Promise<string[]>;
private handleResponse;
private handleError;
}
+53
View File
@@ -0,0 +1,53 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Api = void 0;
const axios_1 = __importDefault(require("axios"));
const react_toastify_1 = require("react-toastify");
class Api {
constructor({ basePath } = { basePath: '' }) {
this.axios = axios_1.default.create({ baseURL: `${basePath}/api` });
this.axios.interceptors.response.use(this.handleResponse, this.handleError);
}
getQueues({ status, }) {
return this.axios.get(`/queues/`, { params: { ...status } });
}
retryAll(queueName) {
return this.axios.put(`/queues/${encodeURIComponent(queueName)}/retry`);
}
cleanAllDelayed(queueName) {
return this.axios.put(`/queues/${encodeURIComponent(queueName)}/clean/delayed`);
}
cleanAllFailed(queueName) {
return this.axios.put(`/queues/${encodeURIComponent(queueName)}/clean/failed`);
}
cleanAllCompleted(queueName) {
return this.axios.put(`/queues/${encodeURIComponent(queueName)}/clean/completed`);
}
cleanJob(queueName, jobId) {
return this.axios.put(`/queues/${encodeURIComponent(queueName)}/${jobId}/clean`);
}
retryJob(queueName, jobId) {
return this.axios.put(`/queues/${encodeURIComponent(queueName)}/${jobId}/retry`);
}
promoteJob(queueName, jobId) {
return this.axios.put(`/queues/${encodeURIComponent(queueName)}/${jobId}/promote`);
}
getJobLogs(queueName, jobId) {
return this.axios.get(`/queues/${encodeURIComponent(queueName)}/${jobId}/logs`);
}
handleResponse(response) {
return response.data;
}
async handleError(error) {
var _a, _b;
if ((_a = error.response.data) === null || _a === void 0 ? void 0 : _a.error) {
react_toastify_1.toast.error((_b = error.response.data) === null || _b === void 0 ? void 0 : _b.error, { autoClose: 5000 });
}
return Promise.resolve(error.response.data);
}
}
exports.Api = Api;
//# sourceMappingURL=Api.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"Api.js","sourceRoot":"","sources":["../../../src/ui/services/Api.ts"],"names":[],"mappings":";;;;;;AAAA,kDAA2D;AAC3D,mDAAsC;AAItC,MAAa,GAAG;IAGd,YAAY,EAAE,QAAQ,KAA2B,EAAE,QAAQ,EAAE,EAAE,EAAE;QAC/D,IAAI,CAAC,KAAK,GAAG,eAAK,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,QAAQ,MAAM,EAAE,CAAC,CAAA;QACzD,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,WAAW,CAAC,CAAA;IAC7E,CAAC;IAEM,SAAS,CAAC,EACf,MAAM,GAGP;QACC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,EAAE,GAAG,MAAM,EAAE,EAAE,CAAC,CAAA;IAC9D,CAAC;IAEM,QAAQ,CAAC,SAAiB;QAC/B,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,kBAAkB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAA;IACzE,CAAC;IAEM,eAAe,CAAC,SAAiB;QACtC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CACnB,WAAW,kBAAkB,CAAC,SAAS,CAAC,gBAAgB,CACzD,CAAA;IACH,CAAC;IAEM,cAAc,CAAC,SAAiB;QACrC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CACnB,WAAW,kBAAkB,CAAC,SAAS,CAAC,eAAe,CACxD,CAAA;IACH,CAAC;IAEM,iBAAiB,CAAC,SAAiB;QACxC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CACnB,WAAW,kBAAkB,CAAC,SAAS,CAAC,kBAAkB,CAC3D,CAAA;IACH,CAAC;IAEM,QAAQ,CACb,SAAiB,EACjB,KAAkC;QAElC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CACnB,WAAW,kBAAkB,CAAC,SAAS,CAAC,IAAI,KAAK,QAAQ,CAC1D,CAAA;IACH,CAAC;IAEM,QAAQ,CACb,SAAiB,EACjB,KAAkC;QAElC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CACnB,WAAW,kBAAkB,CAAC,SAAS,CAAC,IAAI,KAAK,QAAQ,CAC1D,CAAA;IACH,CAAC;IAEM,UAAU,CACf,SAAiB,EACjB,KAAkC;QAElC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CACnB,WAAW,kBAAkB,CAAC,SAAS,CAAC,IAAI,KAAK,UAAU,CAC5D,CAAA;IACH,CAAC;IAEM,UAAU,CACf,SAAiB,EACjB,KAAkC;QAElC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CACnB,WAAW,kBAAkB,CAAC,SAAS,CAAC,IAAI,KAAK,OAAO,CACzD,CAAA;IACH,CAAC;IAEO,cAAc,CAAC,QAAuB;QAC5C,OAAO,QAAQ,CAAC,IAAI,CAAA;IACtB,CAAC;IAEO,KAAK,CAAC,WAAW,CAAC,KAAkC;;QAC1D,IAAI,MAAA,KAAK,CAAC,QAAQ,CAAC,IAAI,0CAAE,KAAK,EAAE;YAC9B,sBAAK,CAAC,KAAK,CAAC,MAAA,KAAK,CAAC,QAAQ,CAAC,IAAI,0CAAE,KAAK,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;SAC7D;QAED,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;IAC7C,CAAC;CACF;AArFD,kBAqFC"}