@pax2pay/model-banking 0.1.509 → 0.1.511
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/Card/Restriction/Merchant.ts +19 -94
- package/Card/Restriction/merchants/Merchant.ts +28 -0
- package/Card/Restriction/merchants/airlines.json +957 -0
- package/Card/Restriction/merchants/hotels.json +252 -0
- package/Card/Restriction/merchants/index.ts +765 -0
- package/Card/Restriction/merchants/misc.json +139 -0
- package/User/Access/Permission.ts +47 -0
- package/User/Access/index.ts +19 -0
- package/User/Identity.ts +32 -0
- package/User/JWT/Payload.ts +56 -0
- package/User/JWT/Signer.ts +39 -0
- package/User/JWT/index.ts +57 -0
- package/User/Me.ts +15 -0
- package/User/Password.ts +43 -0
- package/User/index.ts +68 -0
- package/dist/cjs/Card/Restriction/Merchant.d.ts +3 -9
- package/dist/cjs/Card/Restriction/Merchant.js +18 -87
- package/dist/cjs/Card/Restriction/Merchant.js.map +1 -1
- package/dist/cjs/Card/Restriction/merchants/Merchant.d.ts +12 -0
- package/dist/cjs/Card/Restriction/merchants/Merchant.js +26 -0
- package/dist/cjs/Card/Restriction/merchants/Merchant.js.map +1 -0
- package/dist/cjs/Card/Restriction/merchants/index.d.ts +763 -0
- package/dist/cjs/Card/Restriction/merchants/index.js +767 -0
- package/dist/cjs/Card/Restriction/merchants/index.js.map +1 -0
- package/dist/cjs/User/Access/Permission.d.ts +20 -0
- package/dist/cjs/User/Access/Permission.js +47 -0
- package/dist/cjs/User/Access/Permission.js.map +1 -0
- package/dist/cjs/User/Access/index.d.ts +11 -0
- package/dist/cjs/User/Access/index.js +16 -0
- package/dist/cjs/User/Access/index.js.map +1 -0
- package/dist/cjs/User/Identity.d.ts +16 -0
- package/dist/cjs/User/Identity.js +32 -0
- package/dist/cjs/User/Identity.js.map +1 -0
- package/dist/cjs/User/JWT/Payload.d.ts +43 -0
- package/dist/cjs/User/JWT/Payload.js +42 -0
- package/dist/cjs/User/JWT/Payload.js.map +1 -0
- package/dist/cjs/User/JWT/Signer.d.ts +23 -0
- package/dist/cjs/User/JWT/Signer.js +39 -0
- package/dist/cjs/User/JWT/Signer.js.map +1 -0
- package/dist/cjs/User/JWT/index.d.ts +25 -0
- package/dist/cjs/User/JWT/index.js +59 -0
- package/dist/cjs/User/JWT/index.js.map +1 -0
- package/dist/cjs/User/Me.d.ts +9 -0
- package/dist/cjs/User/Me.js +14 -0
- package/dist/cjs/User/Me.js.map +1 -0
- package/dist/cjs/User/Password.d.ts +20 -0
- package/dist/cjs/User/Password.js +44 -0
- package/dist/cjs/User/Password.js.map +1 -0
- package/dist/cjs/User/index.d.ts +46 -0
- package/dist/cjs/User/index.js +54 -0
- package/dist/cjs/User/index.js.map +1 -0
- package/dist/cjs/pax2pay.d.ts +2 -1
- package/dist/cjs/pax2pay.js +5 -3
- package/dist/cjs/pax2pay.js.map +1 -1
- package/dist/mjs/Card/Restriction/Merchant.d.ts +3 -9
- package/dist/mjs/Card/Restriction/Merchant.js +18 -87
- package/dist/mjs/Card/Restriction/Merchant.js.map +1 -1
- package/dist/mjs/Card/Restriction/merchants/Merchant.d.ts +12 -0
- package/dist/mjs/Card/Restriction/merchants/Merchant.js +23 -0
- package/dist/mjs/Card/Restriction/merchants/Merchant.js.map +1 -0
- package/dist/mjs/Card/Restriction/merchants/index.d.ts +763 -0
- package/dist/mjs/Card/Restriction/merchants/index.js +764 -0
- package/dist/mjs/Card/Restriction/merchants/index.js.map +1 -0
- package/dist/mjs/User/Access/Permission.d.ts +20 -0
- package/dist/mjs/User/Access/Permission.js +44 -0
- package/dist/mjs/User/Access/Permission.js.map +1 -0
- package/dist/mjs/User/Access/index.d.ts +11 -0
- package/dist/mjs/User/Access/index.js +13 -0
- package/dist/mjs/User/Access/index.js.map +1 -0
- package/dist/mjs/User/Identity.d.ts +16 -0
- package/dist/mjs/User/Identity.js +28 -0
- package/dist/mjs/User/Identity.js.map +1 -0
- package/dist/mjs/User/JWT/Payload.d.ts +43 -0
- package/dist/mjs/User/JWT/Payload.js +39 -0
- package/dist/mjs/User/JWT/Payload.js.map +1 -0
- package/dist/mjs/User/JWT/Signer.d.ts +23 -0
- package/dist/mjs/User/JWT/Signer.js +35 -0
- package/dist/mjs/User/JWT/Signer.js.map +1 -0
- package/dist/mjs/User/JWT/index.d.ts +25 -0
- package/dist/mjs/User/JWT/index.js +55 -0
- package/dist/mjs/User/JWT/index.js.map +1 -0
- package/dist/mjs/User/Me.d.ts +9 -0
- package/dist/mjs/User/Me.js +11 -0
- package/dist/mjs/User/Me.js.map +1 -0
- package/dist/mjs/User/Password.d.ts +20 -0
- package/dist/mjs/User/Password.js +41 -0
- package/dist/mjs/User/Password.js.map +1 -0
- package/dist/mjs/User/index.d.ts +46 -0
- package/dist/mjs/User/index.js +51 -0
- package/dist/mjs/User/index.js.map +1 -0
- package/dist/mjs/pax2pay.d.ts +2 -1
- package/dist/mjs/pax2pay.js +2 -1
- package/dist/mjs/pax2pay.js.map +1 -1
- package/package.json +1 -1
- package/pax2pay.ts +2 -1
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"name": "PARKWING",
|
|
4
|
+
"mccs": [
|
|
5
|
+
4582
|
|
6
|
+
],
|
|
7
|
+
"category": "Airports and Terminals",
|
|
8
|
+
"startsWith": [
|
|
9
|
+
"PARKWING"
|
|
10
|
+
]
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"name": "Albergo - Food and drinks",
|
|
14
|
+
"mccs": [
|
|
15
|
+
5812
|
|
16
|
+
],
|
|
17
|
+
"category": "Food and drinks",
|
|
18
|
+
"startsWith": [
|
|
19
|
+
"ALBERGO"
|
|
20
|
+
]
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"name": "Amtrak",
|
|
24
|
+
"mccs": [
|
|
25
|
+
4112
|
|
26
|
+
],
|
|
27
|
+
"category": "Alternative Transportation",
|
|
28
|
+
"startsWith": [
|
|
29
|
+
"AMTRAK"
|
|
30
|
+
]
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"name": "Italo Treno",
|
|
34
|
+
"mccs": [
|
|
35
|
+
4112
|
|
36
|
+
],
|
|
37
|
+
"category": "Alternative Transportation",
|
|
38
|
+
"contains": [
|
|
39
|
+
"ITALOTRENO"
|
|
40
|
+
]
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"name": "ILSA WEB",
|
|
44
|
+
"mccs": [
|
|
45
|
+
4112
|
|
46
|
+
],
|
|
47
|
+
"category": "Advertising",
|
|
48
|
+
"contains": [
|
|
49
|
+
"ILSA WEB"
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"name": "Rail Ninja",
|
|
54
|
+
"mccs": [
|
|
55
|
+
4722,
|
|
56
|
+
4789
|
|
57
|
+
],
|
|
58
|
+
"category": "Alternative Transportation",
|
|
59
|
+
"startsWith": [
|
|
60
|
+
"RailNinja"
|
|
61
|
+
]
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"name": "Irish Rail",
|
|
65
|
+
"mccs": [
|
|
66
|
+
4789,
|
|
67
|
+
4112
|
|
68
|
+
],
|
|
69
|
+
"category": "Alternative Transportation",
|
|
70
|
+
"startsWith": [
|
|
71
|
+
"IRISH RAIL"
|
|
72
|
+
]
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"name": "Österreichische Bundesbahnen",
|
|
76
|
+
"mccs": [
|
|
77
|
+
4111
|
|
78
|
+
],
|
|
79
|
+
"category": "Alternative Transportation",
|
|
80
|
+
"startsWith": [
|
|
81
|
+
"OEBB"
|
|
82
|
+
]
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"name": "Rail Europe",
|
|
86
|
+
"mccs": [
|
|
87
|
+
4722
|
|
88
|
+
],
|
|
89
|
+
"category": "Alternative Transportation",
|
|
90
|
+
"startsWith": [
|
|
91
|
+
"RAIL EUROPE"
|
|
92
|
+
]
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"name": "Via Rail Canada",
|
|
96
|
+
"mccs": [
|
|
97
|
+
4112
|
|
98
|
+
],
|
|
99
|
+
"category": "Alternative Transportation",
|
|
100
|
+
"startsWith": [
|
|
101
|
+
"VIA RAIL"
|
|
102
|
+
]
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"name": "Direct Ferries",
|
|
106
|
+
"mccs": [
|
|
107
|
+
4111,
|
|
108
|
+
4411
|
|
109
|
+
],
|
|
110
|
+
"category": "Alternative Transportation",
|
|
111
|
+
"startsWith": [
|
|
112
|
+
"DIRECTF"
|
|
113
|
+
]
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"name": "Booking.com",
|
|
117
|
+
"mccs": [
|
|
118
|
+
4722
|
|
119
|
+
],
|
|
120
|
+
"category": "Travel Agency",
|
|
121
|
+
"startsWith": [
|
|
122
|
+
"BKG*"
|
|
123
|
+
]
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"name": "Advertising",
|
|
127
|
+
"mccs": [
|
|
128
|
+
7311,
|
|
129
|
+
5818
|
|
130
|
+
],
|
|
131
|
+
"contains": [
|
|
132
|
+
"FACEBK",
|
|
133
|
+
"google *ad",
|
|
134
|
+
"googleadwords",
|
|
135
|
+
"facebook"
|
|
136
|
+
],
|
|
137
|
+
"category": "Advertising"
|
|
138
|
+
}
|
|
139
|
+
]
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { isly } from "isly"
|
|
2
|
+
import { typedly } from "typedly"
|
|
3
|
+
|
|
4
|
+
export type Permission = Partial<Record<Permission.Collection, Permission.Level>>
|
|
5
|
+
export namespace Permission {
|
|
6
|
+
export type Realm = Omit<Permission, "user">
|
|
7
|
+
export type Global = Pick<Permission, "user">
|
|
8
|
+
export function check(constraint: Permission, privilege: Permission): boolean {
|
|
9
|
+
return typedly.Object.entries(constraint).every(
|
|
10
|
+
([collection, level]) =>
|
|
11
|
+
Permission.Level.get(privilege[collection]) >= Permission.Level.get(level) ||
|
|
12
|
+
Permission.Level.get(privilege["*"]) >= Permission.Level.get(level)
|
|
13
|
+
)
|
|
14
|
+
}
|
|
15
|
+
export type Level = typeof Level.values[number]
|
|
16
|
+
export namespace Level {
|
|
17
|
+
export const values = ["read", "write", "developer", "admin"] as const
|
|
18
|
+
export const type = isly.string(values)
|
|
19
|
+
export function get(level: Level | undefined): number {
|
|
20
|
+
return level ? value[level] : 0
|
|
21
|
+
}
|
|
22
|
+
export const value: Record<Level, number> = {
|
|
23
|
+
read: 1,
|
|
24
|
+
write: 2,
|
|
25
|
+
developer: 3,
|
|
26
|
+
admin: 4,
|
|
27
|
+
} as const
|
|
28
|
+
}
|
|
29
|
+
export type Collection = typeof Collection.values[number]
|
|
30
|
+
export namespace Collection {
|
|
31
|
+
export const values = [
|
|
32
|
+
"account",
|
|
33
|
+
"card",
|
|
34
|
+
"log",
|
|
35
|
+
"operation",
|
|
36
|
+
"organization",
|
|
37
|
+
"rule", // realm rules
|
|
38
|
+
"settlement",
|
|
39
|
+
"transaction",
|
|
40
|
+
"treasury",
|
|
41
|
+
"user",
|
|
42
|
+
"*",
|
|
43
|
+
] as const
|
|
44
|
+
export const type = isly.string(values)
|
|
45
|
+
}
|
|
46
|
+
export const type = isly.record<Permission>(Collection.type, Level.type)
|
|
47
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { isly } from "isly"
|
|
2
|
+
import { Permission as AccessPermission } from "./Permission"
|
|
3
|
+
|
|
4
|
+
/** read < write < developer < admin */
|
|
5
|
+
export interface Access {
|
|
6
|
+
uk?: Access.Permission.Realm
|
|
7
|
+
eea?: Access.Permission.Realm
|
|
8
|
+
test?: Access.Permission.Realm
|
|
9
|
+
"*"?: Access.Permission.Global
|
|
10
|
+
}
|
|
11
|
+
export namespace Access {
|
|
12
|
+
export import Permission = AccessPermission
|
|
13
|
+
export const type = isly.object({
|
|
14
|
+
uk: Access.Permission.type.optional(),
|
|
15
|
+
eea: Access.Permission.type.optional(),
|
|
16
|
+
test: Access.Permission.type.optional(),
|
|
17
|
+
"*": isly.object({ user: Access.Permission.Level.type.optional() }).optional(),
|
|
18
|
+
})
|
|
19
|
+
}
|
package/User/Identity.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { gracely } from "gracely"
|
|
2
|
+
import { http } from "cloudly-http"
|
|
3
|
+
import { Realm } from "../Realm"
|
|
4
|
+
import { Access } from "./Access"
|
|
5
|
+
import { JWT } from "./JWT"
|
|
6
|
+
|
|
7
|
+
export class Identity {
|
|
8
|
+
get realm(): Realm {
|
|
9
|
+
return this.payload.realm
|
|
10
|
+
}
|
|
11
|
+
constructor(public readonly payload: JWT.Payload, private readonly jwt: string) {}
|
|
12
|
+
|
|
13
|
+
authenticate(constraint: Access.Permission | Access.Permission[]): Identity | gracely.Error {
|
|
14
|
+
let allowed: boolean
|
|
15
|
+
if (Array.isArray(constraint))
|
|
16
|
+
allowed = constraint.some(c => this.authenticate(c))
|
|
17
|
+
else
|
|
18
|
+
allowed = Access.Permission.check(constraint, this.payload.permission)
|
|
19
|
+
return allowed ? this : gracely.client.forbidden()
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Key will default to production jwt verification key */
|
|
23
|
+
static async open(
|
|
24
|
+
authorization: string | undefined,
|
|
25
|
+
options: { whitelist?: JWT.Whitelist; key?: string }
|
|
26
|
+
): Promise<Identity | gracely.Error> {
|
|
27
|
+
const jwt = authorization?.startsWith("Bearer ") ? authorization.replace("Bearer ", "") : undefined
|
|
28
|
+
const payload = jwt ? await JWT.open({ public: options.key }, options.whitelist).verify(jwt) : undefined
|
|
29
|
+
return jwt && payload ? new Identity(payload, jwt) : gracely.client.unauthorized()
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export namespace Identity {}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { authly } from "authly"
|
|
2
|
+
import { isly } from "isly"
|
|
3
|
+
import { Realm } from "../../Realm"
|
|
4
|
+
import { Access } from "../Access"
|
|
5
|
+
|
|
6
|
+
export type Payload = Payload.LongTerm | Payload.ShortTerm
|
|
7
|
+
export namespace Payload {
|
|
8
|
+
export interface Creatable {
|
|
9
|
+
sub: string
|
|
10
|
+
permission: Access.Permission
|
|
11
|
+
realm: Realm
|
|
12
|
+
}
|
|
13
|
+
export namespace Creatable {
|
|
14
|
+
export const type = isly.object<Creatable>({
|
|
15
|
+
sub: isly.string(),
|
|
16
|
+
permission: Access.Permission.type,
|
|
17
|
+
realm: Realm.type,
|
|
18
|
+
})
|
|
19
|
+
}
|
|
20
|
+
export interface Base extends authly.Payload {
|
|
21
|
+
aud: string
|
|
22
|
+
iat: number
|
|
23
|
+
iss: string
|
|
24
|
+
sub: string
|
|
25
|
+
permission: Access.Permission
|
|
26
|
+
realm: Realm
|
|
27
|
+
}
|
|
28
|
+
export namespace Base {
|
|
29
|
+
export const type = isly.object<Payload>({
|
|
30
|
+
aud: isly.string(),
|
|
31
|
+
iat: isly.number(),
|
|
32
|
+
iss: isly.string(),
|
|
33
|
+
sub: isly.string(),
|
|
34
|
+
permission: Access.Permission.type,
|
|
35
|
+
realm: Realm.type,
|
|
36
|
+
})
|
|
37
|
+
}
|
|
38
|
+
export interface LongTerm extends Base {
|
|
39
|
+
id: string
|
|
40
|
+
}
|
|
41
|
+
export namespace LongTerm {
|
|
42
|
+
export const type = Base.type.extend<LongTerm>({ id: isly.string() })
|
|
43
|
+
}
|
|
44
|
+
export interface ShortTerm extends Base {
|
|
45
|
+
exp: number
|
|
46
|
+
}
|
|
47
|
+
export namespace ShortTerm {
|
|
48
|
+
export const type = Base.type.extend<ShortTerm>({ exp: isly.number() })
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export const configuration = {
|
|
52
|
+
aud: "https://banking.pax2pay.app",
|
|
53
|
+
iss: "pax2pay",
|
|
54
|
+
}
|
|
55
|
+
export const type = isly.union<Payload>(LongTerm.type, ShortTerm.type)
|
|
56
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { authly } from "authly"
|
|
2
|
+
import { Payload } from "./Payload"
|
|
3
|
+
|
|
4
|
+
export class Signer {
|
|
5
|
+
constructor(private readonly key?: { public?: string; private?: string }) {}
|
|
6
|
+
|
|
7
|
+
/** Duration in seconds */
|
|
8
|
+
async sign(data: Payload.Creatable, duration: number | "infinite" = 60 * 60 * 12): Promise<string | undefined> {
|
|
9
|
+
let result: string | undefined
|
|
10
|
+
if (duration === "infinite") {
|
|
11
|
+
const signer = Signer.create({ key: this.key })
|
|
12
|
+
result = await signer?.sign({ id: authly.Identifier.generate(16), ...data })
|
|
13
|
+
} else {
|
|
14
|
+
const signer = Signer.create({ key: this.key, duration })
|
|
15
|
+
result = await signer?.sign({ ...data })
|
|
16
|
+
}
|
|
17
|
+
return result
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
static open(key?: { public?: string; private?: string }): Signer {
|
|
21
|
+
return new this(key)
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export namespace Signer {
|
|
25
|
+
export function create<T extends authly.Payload>(options: {
|
|
26
|
+
key?: { public?: string; private?: string }
|
|
27
|
+
duration?: number
|
|
28
|
+
}): authly.Issuer<T> | undefined {
|
|
29
|
+
const signer = authly.Issuer.create(
|
|
30
|
+
Payload.configuration.iss,
|
|
31
|
+
authly.Algorithm.RS256(options.key?.public, options.key?.private)
|
|
32
|
+
)
|
|
33
|
+
if (signer) {
|
|
34
|
+
signer.duration = options.duration
|
|
35
|
+
signer.audience = Payload.configuration.aud
|
|
36
|
+
}
|
|
37
|
+
return signer
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { authly } from "authly"
|
|
2
|
+
import { Realm } from "../../Realm"
|
|
3
|
+
import { Payload as JWTPayload } from "./Payload"
|
|
4
|
+
import { Signer as JWTSigner } from "./Signer"
|
|
5
|
+
|
|
6
|
+
export class JWT {
|
|
7
|
+
#verifier?: authly.Verifier<JWT.Payload>
|
|
8
|
+
private get verifier(): authly.Verifier<JWT.Payload> | undefined {
|
|
9
|
+
if (!this.#verifier && this.key?.public) {
|
|
10
|
+
const algorithm = authly.Algorithm.RS256(this.key.public)
|
|
11
|
+
this.#verifier = algorithm ? authly.Verifier.create(algorithm) : undefined
|
|
12
|
+
}
|
|
13
|
+
return this.#verifier
|
|
14
|
+
}
|
|
15
|
+
#signer?: JWTSigner
|
|
16
|
+
private get signer(): JWTSigner | undefined {
|
|
17
|
+
return this.key?.private ? (this.#signer ??= JWTSigner.open(this.key)) : undefined
|
|
18
|
+
}
|
|
19
|
+
get sign() {
|
|
20
|
+
return this.signer?.sign
|
|
21
|
+
}
|
|
22
|
+
private constructor(
|
|
23
|
+
private readonly key?: { public?: string; private?: string },
|
|
24
|
+
readonly whitelist?: JWT.Whitelist
|
|
25
|
+
) {}
|
|
26
|
+
|
|
27
|
+
async verify(token: string): Promise<JWT.Payload | undefined> {
|
|
28
|
+
const verified = await this.verifier?.verify(token, JWT.Payload.configuration.aud)
|
|
29
|
+
delete verified?.token
|
|
30
|
+
return JWT.Payload.type.is(verified) &&
|
|
31
|
+
verified?.iss == JWT.Payload.configuration.iss &&
|
|
32
|
+
(verified.exp || (verified.id && this.whitelist?.[verified.realm]?.some(e => e.id === verified.id)))
|
|
33
|
+
? verified
|
|
34
|
+
: undefined
|
|
35
|
+
}
|
|
36
|
+
async unpack(token: string): Promise<JWT.Payload | undefined> {
|
|
37
|
+
const unpacked = await JWT.unpack(token)
|
|
38
|
+
delete unpacked?.token
|
|
39
|
+
return unpacked
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
static open(key?: { private?: string; public?: string }, whitelist?: JWT.Whitelist): JWT {
|
|
43
|
+
return new this({ private: key?.private, public: key?.public ?? JWT.key }, whitelist)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export namespace JWT {
|
|
47
|
+
export import Signer = JWTSigner
|
|
48
|
+
export type Whitelist = Partial<Record<Realm, Payload.LongTerm[]>>
|
|
49
|
+
export async function unpack(token: string): Promise<JWT.Payload | undefined> {
|
|
50
|
+
const algorithm = authly.Algorithm.RS256(undefined)
|
|
51
|
+
const verifier = algorithm ? authly.Verifier.create<JWT.Payload>(algorithm) : undefined
|
|
52
|
+
return verifier?.unpack(token)
|
|
53
|
+
}
|
|
54
|
+
export import Payload = JWTPayload
|
|
55
|
+
export const key =
|
|
56
|
+
"MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA2W8CD2kpfS4QIRV2/rgm4NVvsvJsYNMHtnIl9ADvO3A81hAmRKvOAPVoXICe6+EuZ47jGjGL7f48GEoQuITfBPv/MosCDj1YhJ56ILDynCSd8FlxDrhv8pl5IquST7tcL6Hc6m+vuvoTLrFQ5QqNxv0a5eDd/YTrWv7SUuRfBEhYd/wMysGynN3QauHqy5ceBCt1nv1MJLGlSzczMRK7wjy1zi2g9NCHZBOoo1HXOpi727Xh+YXHc9EP2TN0oOXyxykv45nkGIDI0Qek3/pfkavClBffc1sEqA+rUx7YqRN9KGYxwLMLug+NOOh3ptqjfobXbR5fx/sUWhvcjUMTE1JreTrWYbGmVnjd/SeYSClfmGhdTBUfqnZbaABv0ruTXva18qRhP4y143vHMk/k8HzbuROTKAzrtEeLIjgwUgDcnE+JwDqcb8tKSGV6i++TiTldlSBCRTT4dK2hpHJje80b2abqtrbCkxbJlT98UsAAoiq2eW1X6lYmCfiGCJPkfswibQ2tPAKKNe/2xuHPsjx4FuXGmV0dbzmCwSIQoApXqOvKzoNFi6AaKIjxfNmiEigLwKpNrw08H0lVZbq/9MMxI3TzMTZjY9QmBKVLSGy3Z6IJqZpyK22lv7whJcllG0Qw8tv8+7wmC8SR3+4jpuxuFGZ+69CW+otx+CPMJjcCAwEAAQ=="
|
|
57
|
+
}
|
package/User/Me.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { isly } from "isly"
|
|
2
|
+
import { Realm } from "../Realm"
|
|
3
|
+
|
|
4
|
+
export interface Me {
|
|
5
|
+
email: string
|
|
6
|
+
password: string
|
|
7
|
+
realm: Realm
|
|
8
|
+
}
|
|
9
|
+
export namespace Me {
|
|
10
|
+
export const type = isly.object<Me>({
|
|
11
|
+
email: isly.string(),
|
|
12
|
+
password: isly.string(),
|
|
13
|
+
realm: Realm.type,
|
|
14
|
+
})
|
|
15
|
+
}
|
package/User/Password.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { cryptly } from "cryptly"
|
|
2
|
+
import { gracely } from "gracely"
|
|
3
|
+
import { isoly } from "isoly"
|
|
4
|
+
import { isly } from "isly"
|
|
5
|
+
|
|
6
|
+
export interface Password {
|
|
7
|
+
hash: cryptly.Password.Hash
|
|
8
|
+
changed: isoly.DateTime
|
|
9
|
+
}
|
|
10
|
+
export namespace Password {
|
|
11
|
+
export interface Creatable {
|
|
12
|
+
new: string
|
|
13
|
+
repeat: string
|
|
14
|
+
}
|
|
15
|
+
export namespace Creatable {
|
|
16
|
+
export const type = isly.object<Creatable>({
|
|
17
|
+
new: isly.string(),
|
|
18
|
+
repeat: isly.string(),
|
|
19
|
+
})
|
|
20
|
+
}
|
|
21
|
+
export async function create(creatable: Creatable, pepper: string | undefined): Promise<Password | gracely.Error> {
|
|
22
|
+
let result: Awaited<ReturnType<typeof create>>
|
|
23
|
+
if (creatable.new !== creatable.repeat)
|
|
24
|
+
result = gracely.client.forbidden("The new password and the repeated password do not match.")
|
|
25
|
+
else if (!pepper)
|
|
26
|
+
result = gracely.server.backendFailure("The password cannot be created without a pepper.")
|
|
27
|
+
else
|
|
28
|
+
result = { hash: await hash(creatable.new, pepper), changed: isoly.DateTime.now() }
|
|
29
|
+
return result
|
|
30
|
+
}
|
|
31
|
+
export function salt(): string {
|
|
32
|
+
return cryptly.Base64.encode(cryptly.RandomValue.generate(new Uint8Array(64)).toString())
|
|
33
|
+
}
|
|
34
|
+
export async function hash(password: string, pepper: string): Promise<cryptly.Password.Hash> {
|
|
35
|
+
return cryptly.Password.hash(signer(pepper), password, salt())
|
|
36
|
+
}
|
|
37
|
+
export async function verify(password: string, hash: cryptly.Password.Hash, pepper: string): Promise<boolean> {
|
|
38
|
+
return cryptly.Password.verify(signer(pepper), hash, password)
|
|
39
|
+
}
|
|
40
|
+
function signer(pepper: string): { sign: (data: string) => Promise<string> } {
|
|
41
|
+
return cryptly.Signer.create("HMAC", "SHA-512", pepper)
|
|
42
|
+
}
|
|
43
|
+
}
|
package/User/index.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { isoly } from "isoly"
|
|
2
|
+
import { isly } from "isly"
|
|
3
|
+
import { Realm } from "../Realm"
|
|
4
|
+
import { Access as UserAccess } from "./Access"
|
|
5
|
+
import { Identity as UserIdentity } from "./Identity"
|
|
6
|
+
import { JWT as UserJWT } from "./JWT"
|
|
7
|
+
import { Me as UserMe } from "./Me"
|
|
8
|
+
import { Password as UserPassword } from "./Password"
|
|
9
|
+
|
|
10
|
+
export interface User {
|
|
11
|
+
email: string
|
|
12
|
+
access: User.Access
|
|
13
|
+
changed: isoly.DateTime
|
|
14
|
+
created: isoly.DateTime
|
|
15
|
+
password: {
|
|
16
|
+
changed: isoly.DateTime
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export namespace User {
|
|
20
|
+
export import Access = UserAccess
|
|
21
|
+
export import Identity = UserIdentity
|
|
22
|
+
export import JWT = UserJWT
|
|
23
|
+
export import Me = UserMe
|
|
24
|
+
export import Password = UserPassword
|
|
25
|
+
export function fromInvite(invite: Invite): User {
|
|
26
|
+
const now = isoly.DateTime.now()
|
|
27
|
+
return {
|
|
28
|
+
email: invite.email,
|
|
29
|
+
access: invite.access,
|
|
30
|
+
changed: now,
|
|
31
|
+
created: now,
|
|
32
|
+
password: {
|
|
33
|
+
changed: now,
|
|
34
|
+
},
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export function toJWTPayloadCreatable(user: User, realm: Realm): User.JWT.Payload.Creatable {
|
|
38
|
+
return {
|
|
39
|
+
sub: user.email,
|
|
40
|
+
permission: { ...(user.access[realm] ?? {}), ...(user.access["*"] ?? {}) },
|
|
41
|
+
realm,
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
export interface Creatable {
|
|
45
|
+
invite: string
|
|
46
|
+
password: Password.Creatable
|
|
47
|
+
}
|
|
48
|
+
export namespace Creatable {
|
|
49
|
+
export const type = isly.object<Creatable>({
|
|
50
|
+
invite: isly.string(),
|
|
51
|
+
password: isly.object({ new: isly.string(), repeat: isly.string() }),
|
|
52
|
+
})
|
|
53
|
+
}
|
|
54
|
+
export interface Invite {
|
|
55
|
+
id: string
|
|
56
|
+
email: string
|
|
57
|
+
access: Access
|
|
58
|
+
}
|
|
59
|
+
export namespace Invite {
|
|
60
|
+
export interface Creatable {
|
|
61
|
+
email: string
|
|
62
|
+
access: Access
|
|
63
|
+
}
|
|
64
|
+
export namespace Creatable {
|
|
65
|
+
export const type = isly.object<Creatable>({ email: isly.string(), access: Access.type })
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -3,14 +3,8 @@ import { isly as isly2 } from "isly2";
|
|
|
3
3
|
import type { Transaction } from "../../Transaction";
|
|
4
4
|
export type Merchant = typeof Merchant.values[number];
|
|
5
5
|
export declare namespace Merchant {
|
|
6
|
-
const values:
|
|
7
|
-
const type: isly.Type<"united airlines" | "
|
|
8
|
-
const type2: isly2.String<"united airlines" | "
|
|
9
|
-
type Checker = (merchant: Merchant, transaction: Transaction.Creatable.CardTransaction | Transaction.PreTransaction.Authorization) => boolean;
|
|
10
|
-
type Attribute = {
|
|
11
|
-
mccs: string[];
|
|
12
|
-
checkers?: Checker[];
|
|
13
|
-
};
|
|
14
|
-
const attributes: Record<Merchant, Attribute>;
|
|
6
|
+
const values: ("ryanair" | "easyjet" | "wizzair" | "aer lingus" | "air malta" | "vueling" | "jet2" | "eurowings" | "turkish air" | "tap" | "pegasus" | "royal air maroc" | "qatar air" | "blue island" | "klm" | "iberia" | "emirates" | "aegean airlines" | "tui" | "united airlines" | "cathay pacific airlines" | "air serbia" | "copa air" | "bamboo airways" | "latam airlines" | "flydubai" | "condor" | "transavia" | "austrian air" | "alitalia" | "apg airlines" | "iceland air" | "flyone" | "avianca" | "brussels airlines" | "saudia" | "aeromexico" | "gulf air" | "ethiopian airlines" | "egypt air" | "albawings" | "iberojet" | "norwegian air" | "vistara" | "air greenland" | "sky express" | "air canada" | "philippine airlines" | "south african airlink" | "air benelux" | "tunisair" | "lufthansa" | "corendon airlines" | "uganda airlines" | "freebird airlines" | "kenya airway" | "kuwait air" | "british airways" | "czech airlines" | "lot polish airlines" | "volotea" | "flybe" | "bulgaria air" | "sas" | "qantas" | "air india" | "air europa" | "royal jordanian" | "virgin atlantic" | "flexflight" | "rwandair" | "hahn air" | "american air" | "pakistan international airlines" | "singapore airlines" | "delta air lines" | "croatia airlines" | "air asia" | "hawaiian airlines" | "oman air" | "etihad air" | "middle east airlines" | "logan air" | "aurigny" | "eastern airways" | "sun express" | "spirit air" | "air france" | "malaysia airlines" | "finnair" | "swiss air" | "air china" | "ana air" | "ae bsp" | "thai airways" | "jet blue" | "westjet" | "aerolineas" | "air seoul" | "azerbaijan airlines" | "air dolomiti" | "bangkok airways" | "china airlines" | "china eastern airlines" | "eva air" | "jetstar airways" | "km malta airlines" | "ita airways" | "china southern airlines" | "world2fly" | "sata denmark" | "air baltic" | "ajet" | "flynorse" | "hainan air" | "sichuan airlines" | "korean air" | "gol airlines" | "azul brazilian airlines" | "flysafair" | "air mauritius" | "alaska airlines" | "allegiant air" | "plus ultra líneas aéreas" | "parkwing" | "albergo - food and drinks" | "amtrak" | "italo treno" | "ilsa web" | "rail ninja" | "irish rail" | "österreichische bundesbahnen" | "rail europe" | "via rail canada" | "direct ferries" | "booking.com" | "advertising" | "best western" | "una hotels" | "unaway hotels" | "albergo - lodging" | "leonardo hotels" | "hotel mercure" | "nh hotels & resorts" | "novotel hotels" | "ac hotels" | "marriott hotels" | "sheraton hotels and resorts" | "ih hotels" | "ibis hotels" | "hyatt hotels & resorts" | "hilton hotels & resorts" | "holiday inn" | "four seasons" | "doubletree by hilton" | "crowne plaza hotels")[];
|
|
7
|
+
const type: isly.Type<"ryanair" | "easyjet" | "wizzair" | "aer lingus" | "air malta" | "vueling" | "jet2" | "eurowings" | "turkish air" | "tap" | "pegasus" | "royal air maroc" | "qatar air" | "blue island" | "klm" | "iberia" | "emirates" | "aegean airlines" | "tui" | "united airlines" | "cathay pacific airlines" | "air serbia" | "copa air" | "bamboo airways" | "latam airlines" | "flydubai" | "condor" | "transavia" | "austrian air" | "alitalia" | "apg airlines" | "iceland air" | "flyone" | "avianca" | "brussels airlines" | "saudia" | "aeromexico" | "gulf air" | "ethiopian airlines" | "egypt air" | "albawings" | "iberojet" | "norwegian air" | "vistara" | "air greenland" | "sky express" | "air canada" | "philippine airlines" | "south african airlink" | "air benelux" | "tunisair" | "lufthansa" | "corendon airlines" | "uganda airlines" | "freebird airlines" | "kenya airway" | "kuwait air" | "british airways" | "czech airlines" | "lot polish airlines" | "volotea" | "flybe" | "bulgaria air" | "sas" | "qantas" | "air india" | "air europa" | "royal jordanian" | "virgin atlantic" | "flexflight" | "rwandair" | "hahn air" | "american air" | "pakistan international airlines" | "singapore airlines" | "delta air lines" | "croatia airlines" | "air asia" | "hawaiian airlines" | "oman air" | "etihad air" | "middle east airlines" | "logan air" | "aurigny" | "eastern airways" | "sun express" | "spirit air" | "air france" | "malaysia airlines" | "finnair" | "swiss air" | "air china" | "ana air" | "ae bsp" | "thai airways" | "jet blue" | "westjet" | "aerolineas" | "air seoul" | "azerbaijan airlines" | "air dolomiti" | "bangkok airways" | "china airlines" | "china eastern airlines" | "eva air" | "jetstar airways" | "km malta airlines" | "ita airways" | "china southern airlines" | "world2fly" | "sata denmark" | "air baltic" | "ajet" | "flynorse" | "hainan air" | "sichuan airlines" | "korean air" | "gol airlines" | "azul brazilian airlines" | "flysafair" | "air mauritius" | "alaska airlines" | "allegiant air" | "plus ultra líneas aéreas" | "parkwing" | "albergo - food and drinks" | "amtrak" | "italo treno" | "ilsa web" | "rail ninja" | "irish rail" | "österreichische bundesbahnen" | "rail europe" | "via rail canada" | "direct ferries" | "booking.com" | "advertising" | "best western" | "una hotels" | "unaway hotels" | "albergo - lodging" | "leonardo hotels" | "hotel mercure" | "nh hotels & resorts" | "novotel hotels" | "ac hotels" | "marriott hotels" | "sheraton hotels and resorts" | "ih hotels" | "ibis hotels" | "hyatt hotels & resorts" | "hilton hotels & resorts" | "holiday inn" | "four seasons" | "doubletree by hilton" | "crowne plaza hotels">;
|
|
8
|
+
const type2: isly2.String<"ryanair" | "easyjet" | "wizzair" | "aer lingus" | "air malta" | "vueling" | "jet2" | "eurowings" | "turkish air" | "tap" | "pegasus" | "royal air maroc" | "qatar air" | "blue island" | "klm" | "iberia" | "emirates" | "aegean airlines" | "tui" | "united airlines" | "cathay pacific airlines" | "air serbia" | "copa air" | "bamboo airways" | "latam airlines" | "flydubai" | "condor" | "transavia" | "austrian air" | "alitalia" | "apg airlines" | "iceland air" | "flyone" | "avianca" | "brussels airlines" | "saudia" | "aeromexico" | "gulf air" | "ethiopian airlines" | "egypt air" | "albawings" | "iberojet" | "norwegian air" | "vistara" | "air greenland" | "sky express" | "air canada" | "philippine airlines" | "south african airlink" | "air benelux" | "tunisair" | "lufthansa" | "corendon airlines" | "uganda airlines" | "freebird airlines" | "kenya airway" | "kuwait air" | "british airways" | "czech airlines" | "lot polish airlines" | "volotea" | "flybe" | "bulgaria air" | "sas" | "qantas" | "air india" | "air europa" | "royal jordanian" | "virgin atlantic" | "flexflight" | "rwandair" | "hahn air" | "american air" | "pakistan international airlines" | "singapore airlines" | "delta air lines" | "croatia airlines" | "air asia" | "hawaiian airlines" | "oman air" | "etihad air" | "middle east airlines" | "logan air" | "aurigny" | "eastern airways" | "sun express" | "spirit air" | "air france" | "malaysia airlines" | "finnair" | "swiss air" | "air china" | "ana air" | "ae bsp" | "thai airways" | "jet blue" | "westjet" | "aerolineas" | "air seoul" | "azerbaijan airlines" | "air dolomiti" | "bangkok airways" | "china airlines" | "china eastern airlines" | "eva air" | "jetstar airways" | "km malta airlines" | "ita airways" | "china southern airlines" | "world2fly" | "sata denmark" | "air baltic" | "ajet" | "flynorse" | "hainan air" | "sichuan airlines" | "korean air" | "gol airlines" | "azul brazilian airlines" | "flysafair" | "air mauritius" | "alaska airlines" | "allegiant air" | "plus ultra líneas aéreas" | "parkwing" | "albergo - food and drinks" | "amtrak" | "italo treno" | "ilsa web" | "rail ninja" | "irish rail" | "österreichische bundesbahnen" | "rail europe" | "via rail canada" | "direct ferries" | "booking.com" | "advertising" | "best western" | "una hotels" | "unaway hotels" | "albergo - lodging" | "leonardo hotels" | "hotel mercure" | "nh hotels & resorts" | "novotel hotels" | "ac hotels" | "marriott hotels" | "sheraton hotels and resorts" | "ih hotels" | "ibis hotels" | "hyatt hotels & resorts" | "hilton hotels & resorts" | "holiday inn" | "four seasons" | "doubletree by hilton" | "crowne plaza hotels">;
|
|
15
9
|
function check(merchant: Merchant, transaction: Transaction.Creatable.CardTransaction | Transaction.PreTransaction.Authorization): boolean;
|
|
16
10
|
}
|