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
+94
View File
@@ -0,0 +1,94 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = formatDistance;
var formatDistanceLocale = {
lessThanXSeconds: {
one: 'bir saniyədən az',
other: '{{count}} bir saniyədən az'
},
xSeconds: {
one: '1 saniyə',
other: '{{count}} saniyə'
},
halfAMinute: 'yarım dəqiqə',
lessThanXMinutes: {
one: 'bir dəqiqədən az',
other: '{{count}} bir dəqiqədən az'
},
xMinutes: {
one: 'bir dəqiqə',
other: '{{count}} dəqiqə'
},
aboutXHours: {
one: 'təxminən 1 saat',
other: 'təxminən {{count}} saat'
},
xHours: {
one: '1 saat',
other: '{{count}} saat'
},
xDays: {
one: '1 gün',
other: '{{count}} gün'
},
aboutXWeeks: {
one: 'təxminən 1 həftə',
other: 'təxminən {{count}} həftə'
},
xWeeks: {
one: '1 həftə',
other: '{{count}} həftə'
},
aboutXMonths: {
one: 'təxminən 1 ay',
other: 'təxminən {{count}} ay'
},
xMonths: {
one: '1 ay',
other: '{{count}} ay'
},
aboutXYears: {
one: 'təxminən 1 il',
other: 'təxminən {{count}} il'
},
xYears: {
one: '1 il',
other: '{{count}} il'
},
overXYears: {
one: '1 ildən çox',
other: '{{count}} ildən çox'
},
almostXYears: {
one: 'demək olar ki 1 il',
other: 'demək olar ki {{count}} il'
}
};
function formatDistance(token, count, options) {
options = options || {};
var result;
if (typeof formatDistanceLocale[token] === 'string') {
result = formatDistanceLocale[token];
} else if (count === 1) {
result = formatDistanceLocale[token].one;
} else {
result = formatDistanceLocale[token].other.replace('{{count}}', count);
}
if (options.addSuffix) {
if (options.comparison > 0) {
return result + ' əvvəl';
} else {
return result + ' sonra';
}
}
return result;
}
module.exports = exports.default;
+46
View File
@@ -0,0 +1,46 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _index = _interopRequireDefault(require("../../../_lib/buildFormatLongFn/index.js"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var dateFormats = {
full: "EEEE, do MMMM y 'il'",
long: "do MMMM y 'il'",
medium: "d MMM y 'il'",
short: 'dd.MM.yyyy'
};
var timeFormats = {
full: 'H:mm:ss zzzz',
long: 'H:mm:ss z',
medium: 'H:mm:ss',
short: 'H:mm'
};
var dateTimeFormats = {
full: "{{date}} {{time}} - 'də'",
long: "{{date}} {{time}} - 'də'",
medium: '{{date}}, {{time}}',
short: '{{date}}, {{time}}'
};
var formatLong = {
date: (0, _index.default)({
formats: dateFormats,
defaultWidth: 'full'
}),
time: (0, _index.default)({
formats: timeFormats,
defaultWidth: 'full'
}),
dateTime: (0, _index.default)({
formats: dateTimeFormats,
defaultWidth: 'full'
})
};
var _default = formatLong;
exports.default = _default;
module.exports = exports.default;
+20
View File
@@ -0,0 +1,20 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = formatRelative;
var formatRelativeLocale = {
lastWeek: "'sonuncu' eeee p -'də'",
yesterday: "'dünən' p -'də'",
today: "'bugün' p -'də'",
tomorrow: "'sabah' p -'də'",
nextWeek: "eeee p -'də'",
other: 'P'
};
function formatRelative(token, _date, _baseDate, _options) {
return formatRelativeLocale[token];
}
module.exports = exports.default;
+170
View File
@@ -0,0 +1,170 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _index = _interopRequireDefault(require("../../../_lib/buildLocalizeFn/index.js"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var eraValues = {
narrow: ['B', 'A'],
abbreviated: ['BC', 'AD'],
wide: ["Hz. İsa'dan öncə", 'Anno Domini']
};
var quarterValues = {
narrow: ['1', '2', '3', '4'],
abbreviated: ['K1', 'K2', 'K3', 'K4'],
wide: ['1ci kvartal', '2ci kvartal', '3cü kvartal', '4cü kvartal'] // Note: in English, the names of days of the week and months are capitalized.
// If you are making a new locale based on this one, check if the same is true for the language you're working on.
// Generally, formatted dates should look like they are in the middle of a sentence,
// e.g. in Spanish language the weekdays and months should be in the lowercase.
};
var monthValues = {
narrow: ['Y', 'F', 'M', 'A', 'M', 'I', 'I', 'A', 'S', 'O', 'N', 'D'],
abbreviated: ['Yan', 'Fev', 'Mar', 'Apr', 'May', 'İyun', 'İyul', 'Avq', 'Sen', 'Okt', 'Noy', 'Dek'],
wide: ['Yanvar', 'Fevral', 'Mart', 'Aprel', 'May', 'İyun', 'İyul', 'Avqust', 'Sentyabr', 'Oktyabr', 'Noyabr', 'Dekabr']
};
var dayValues = {
narrow: ['B.', 'B.e', 'Ç.a', 'Ç.', 'C.a', 'C.', 'Ş.'],
short: ['B.', 'B.e', 'Ç.a', 'Ç.', 'C.a', 'C.', 'Ş.'],
abbreviated: ['Baz', 'Baz.e', 'Çər.a', 'Çər', 'Cüm.a', 'Cüm', 'Şə'],
wide: ['Bazar', 'Bazar ertəsi', 'Çərşənbə axşamı', 'Çərşənbə', 'Cümə axşamı', 'Cümə', 'Şənbə']
};
var dayPeriodValues = {
narrow: {
am: 'am',
pm: 'pm',
midnight: 'gecəyarı',
noon: 'gün',
morning: 'səhər',
afternoon: 'gündüz',
evening: 'axşam',
night: 'gecə'
},
abbreviated: {
am: 'AM',
pm: 'PM',
midnight: 'gecəyarı',
noon: 'gün',
morning: 'səhər',
afternoon: 'gündüz',
evening: 'axşam',
night: 'gecə'
},
wide: {
am: 'a.m.',
pm: 'p.m.',
midnight: 'gecəyarı',
noon: 'gün',
morning: 'səhər',
afternoon: 'gündüz',
evening: 'axşam',
night: 'gecə'
}
};
var formattingDayPeriodValues = {
narrow: {
am: 'a',
pm: 'p',
midnight: 'gecəyarı',
noon: 'gün',
morning: 'səhər',
afternoon: 'gündüz',
evening: 'axşam',
night: 'gecə'
},
abbreviated: {
am: 'AM',
pm: 'PM',
midnight: 'gecəyarı',
noon: 'gün',
morning: 'səhər',
afternoon: 'gündüz',
evening: 'axşam',
night: 'gecə'
},
wide: {
am: 'a.m.',
pm: 'p.m.',
midnight: 'gecəyarı',
noon: 'gün',
morning: 'səhər',
afternoon: 'gündüz',
evening: 'axşam',
night: 'gecə'
}
};
var suffixes = {
1: '-inci',
5: '-inci',
8: '-inci',
70: '-inci',
80: '-inci',
2: '-nci',
7: '-nci',
20: '-nci',
50: '-nci',
3: '-üncü',
4: '-üncü',
100: '-üncü',
6: '-ncı',
9: '-uncu',
10: '-uncu',
30: '-uncu',
60: '-ıncı',
90: '-ıncı'
};
function getSuffix(number) {
if (number === 0) {
// special case for zero
return number + '-ıncı';
}
var a = number % 10,
b = number % 100 - a,
c = number >= 100 ? 100 : null;
return suffixes[a] || suffixes[b] || suffixes[c];
}
function ordinalNumber(dirtyNumber, _dirtyOptions) {
var number = Number(dirtyNumber);
var suffix = getSuffix(number);
return number + suffix;
}
var localize = {
ordinalNumber: ordinalNumber,
era: (0, _index.default)({
values: eraValues,
defaultWidth: 'wide'
}),
quarter: (0, _index.default)({
values: quarterValues,
defaultWidth: 'wide',
argumentCallback: function (quarter) {
return Number(quarter) - 1;
}
}),
month: (0, _index.default)({
values: monthValues,
defaultWidth: 'wide'
}),
day: (0, _index.default)({
values: dayValues,
defaultWidth: 'wide'
}),
dayPeriod: (0, _index.default)({
values: dayPeriodValues,
defaultWidth: 'wide',
formattingValues: formattingDayPeriodValues,
defaultFormattingWidth: 'wide'
})
};
var _default = localize;
exports.default = _default;
module.exports = exports.default;
+114
View File
@@ -0,0 +1,114 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _index = _interopRequireDefault(require("../../../_lib/buildMatchPatternFn/index.js"));
var _index2 = _interopRequireDefault(require("../../../_lib/buildMatchFn/index.js"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var matchOrdinalNumberPattern = /^(\d+)(-?(ci|inci|nci|uncu|üncü|ncı))?/i;
var parseOrdinalNumberPattern = /\d+/i;
var matchEraPatterns = {
narrow: /^(b|a)$/i,
abbreviated: /^(b\.?\s?c\.?|b\.?\s?c\.?\s?e\.?|a\.?\s?d\.?|c\.?\s?e\.?)$/i,
wide: /^(Hz. İsa'dan öncə|ümumi eradan əvvəl|anno domini|ümumi dövr)$/i
};
var parseEraPatterns = {
any: [/^b$/i, /^(a|c)$/i]
};
var matchQuarterPatterns = {
narrow: /^[1234]$/i,
abbreviated: /^K[1234]$/i,
wide: /^[1234](ci)? kvartal$/i
};
var parseQuarterPatterns = {
any: [/1/i, /2/i, /3/i, /4/i]
};
var matchMonthPatterns = {
narrow: /^[(?-i)yfmaisond]$/i,
abbreviated: /^(Yan|Fev|Mar|Apr|May|İyun|İyul|Avq|Sen|Okt|Noy|Dek)$/i,
wide: /^(Yanvar|Fevral|Mart|Aprel|May|İyun|İyul|Avgust|Sentyabr|Oktyabr|Noyabr|Dekabr)$/i
};
var parseMonthPatterns = {
narrow: [/^[(?-i)y]$/i, /^[(?-i)f]$/i, /^[(?-i)m]$/i, /^[(?-i)a]$/i, /^[(?-i)m]$/i, /^[(?-i)i]$/i, /^[(?-i)i]$/i, /^[(?-i)a]$/i, /^[(?-i)s]$/i, /^[(?-i)o]$/i, /^[(?-i)n]$/i, /^[(?-i)d]$/i],
abbreviated: [/^Yan$/i, /^Fev$/i, /^Mar$/i, /^Apr$/i, /^May$/i, /^İyun$/i, /^İyul$/i, /^Avg$/i, /^Sen$/i, /^Okt$/i, /^Noy$/i, /^Dek$/i],
wide: [/^Yanvar$/i, /^Fevral$/i, /^Mart$/i, /^Aprel$/i, /^May$/i, /^İyun$/i, /^İyul$/i, /^Avgust$/i, /^Sentyabr$/i, /^Oktyabr$/i, /^Noyabr$/i, /^Dekabr$/i]
};
var matchDayPatterns = {
narrow: /^(B\.|B\.e|Ç\.a|Ç\.|C\.a|C\.|Ş\.)$/i,
short: /^(B\.|B\.e|Ç\.a|Ç\.|C\.a|C\.|Ş\.)$/i,
abbreviated: /^(Baz\.e|Çər|Çər\.a|Cüm|Cüm\.a|Şə)$/i,
wide: /^(Bazar|Bazar ertəsi|Çərşənbə axşamı|Çərşənbə|Cümə axşamı|Cümə|Şənbə)$/i
};
var parseDayPatterns = {
narrow: [/^B\.$/i, /^B\.e$/i, /^Ç\.a$/i, /^Ç\.$/i, /^C\.a$/i, /^C\.$/i, /^Ş\.$/i],
abbreviated: [/^Baz\.e$/i, /^Çər$/i, /^Çər\.a$/i, /^Cüm$/i, /^Cüm\.a$/i, /^Şə$/i],
wide: [/^Bazar$/i, /^Bazar ertəsi$/i, /^Çərşənbə axşamı$/i, /^Çərşənbə$/i, /^Cümə axşamı$/i, /^Cümə$/i, /^Şənbə$/i],
any: [/^B\.$/i, /^B\.e$/i, /^Ç\.a$/i, /^Ç\.$/i, /^C\.a$/i, /^C\.$/i, /^Ş\.$/i]
};
var matchDayPeriodPatterns = {
narrow: /^(a|p|gecəyarı|gün|səhər|gündüz|axşam|gecə)$/i,
any: /^(am|pm|a\.m\.|p\.m\.|AM|PM|gecəyarı|gün|səhər|gündüz|axşam|gecə)$/i
};
var parseDayPeriodPatterns = {
any: {
am: /^a$/i,
pm: /^p$/i,
midnight: /^gecəyarı$/i,
noon: /^gün$/i,
morning: /səhər$/i,
afternoon: /gündüz$/i,
evening: /axşam$/i,
night: /gecə$/i
}
};
var match = {
ordinalNumber: (0, _index.default)({
matchPattern: matchOrdinalNumberPattern,
parsePattern: parseOrdinalNumberPattern,
valueCallback: function (value) {
return parseInt(value, 10);
}
}),
era: (0, _index2.default)({
matchPatterns: matchEraPatterns,
defaultMatchWidth: 'wide',
parsePatterns: parseEraPatterns,
defaultParseWidth: 'any'
}),
quarter: (0, _index2.default)({
matchPatterns: matchQuarterPatterns,
defaultMatchWidth: 'wide',
parsePatterns: parseQuarterPatterns,
defaultParseWidth: 'any',
valueCallback: function (index) {
return index + 1;
}
}),
month: (0, _index2.default)({
matchPatterns: matchMonthPatterns,
defaultMatchWidth: 'wide',
parsePatterns: parseMonthPatterns,
defaultParseWidth: 'any'
}),
day: (0, _index2.default)({
matchPatterns: matchDayPatterns,
defaultMatchWidth: 'wide',
parsePatterns: parseDayPatterns,
defaultParseWidth: 'any'
}),
dayPeriod: (0, _index2.default)({
matchPatterns: matchDayPeriodPatterns,
defaultMatchWidth: 'any',
parsePatterns: parseDayPeriodPatterns,
defaultParseWidth: 'any'
})
};
var _default = match;
exports.default = _default;
module.exports = exports.default;