@ozdao/prometheus-framework 0.1.6 → 0.1.8
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/Breadcrumbs.vue_vue_type_style_index_0_lang-561d6db3.js +1 -0
- package/dist/Breadcrumbs.vue_vue_type_style_index_0_lang-9e474158.mjs +1945 -0
- package/dist/ButtonFollow-38d9a720.mjs +131 -0
- package/dist/ButtonFollow-9a33ab06.js +1 -0
- package/dist/CardOrganization-3049931d.mjs +230 -0
- package/dist/CardOrganization-8b376cbb.js +1 -0
- package/dist/Chips-03ff0c34.mjs +108 -0
- package/dist/Chips-4d8ac62e.js +1 -0
- package/dist/Feed-1d0d9853.js +1 -0
- package/dist/Feed-79839e67.mjs +368 -0
- package/dist/Feed-af94027c.js +1 -0
- package/dist/Feed-b616f102.mjs +439 -0
- package/dist/Image-75f5becb.js +9 -0
- package/dist/Image-be69af9c.mjs +477 -0
- package/dist/Popup-d7dbc670.mjs +76 -0
- package/dist/Popup-ee4bd834.js +1 -0
- package/dist/Product-8bee8d1c.mjs +838 -0
- package/dist/Product-a39f3ca3.js +7 -0
- package/dist/ProductEdit-052b0aef.mjs +350 -0
- package/dist/ProductEdit-a322f1ba.js +1 -0
- package/dist/ProfileBlogposts-08f784c3.mjs +64 -0
- package/dist/ProfileBlogposts-d6bba033.js +1 -0
- package/dist/ProfileComments-96f6cde8.mjs +44 -0
- package/dist/ProfileComments-dd923865.js +1 -0
- package/dist/ProfileEvents-1e0c1291.js +1 -0
- package/dist/ProfileEvents-26a72fe2.mjs +56 -0
- package/dist/ProfileLikes-b1060d1e.js +1 -0
- package/dist/ProfileLikes-c8dab14d.mjs +44 -0
- package/dist/ProfileOrganizations-3a879480.mjs +212 -0
- package/dist/ProfileOrganizations-78fef72e.js +1 -0
- package/dist/Publics-8bb9a680.js +1 -0
- package/dist/Publics-ffc08ad7.mjs +123 -0
- package/dist/UploadImage-6344f789.js +1 -0
- package/dist/UploadImage-f04e4bc0.mjs +83 -0
- package/dist/auth-60c81f40.mjs +1836 -0
- package/dist/auth-e8f6d979.js +8 -0
- package/dist/auth.client.cjs +4 -4
- package/dist/auth.client.js +247 -236
- package/dist/auth.server.js +72 -11
- package/dist/auth.server.mjs +72 -11
- package/dist/auth.validation-1d5f2990.mjs +20 -0
- package/dist/auth.validation-2dfb450f.js +1 -0
- package/dist/community.client.cjs +1 -1
- package/dist/community.client.js +11 -11
- package/dist/events.client.cjs +1 -1
- package/dist/events.client.js +9 -9
- package/dist/organizations-4157d81d.js +1 -0
- package/dist/organizations-52438d24.mjs +121 -0
- package/dist/organizations.client-16ee6b43.js +3 -0
- package/dist/organizations.client-cdbaf6aa.mjs +3017 -0
- package/dist/organizations.client.cjs +1 -1
- package/dist/organizations.client.js +11 -11
- package/dist/users.client.cjs +1 -1
- package/dist/users.client.js +258 -239
- package/dist/users.server.js +7 -0
- package/dist/users.server.mjs +7 -0
- package/package.json +1 -1
- package/src/components/CardHeader/CardHeader.vue +2 -1
- package/src/modules/auth/components/pages/SignIn.vue +48 -44
- package/src/modules/auth/controllers/auth.controller.js +42 -11
- package/src/modules/auth/store/auth.js +3 -10
- package/src/modules/auth/utils/server/verifyAppleIdToken.js +57 -0
- package/src/modules/users/components/pages/Profile.vue +20 -6
- package/src/modules/users/components/pages/ProfileEdit.vue +15 -5
- package/src/modules/users/models/user.model.js +9 -1
- package/src/modules/users/store/users.js +2 -1
package/dist/users.server.js
CHANGED
@@ -147,7 +147,14 @@ var user_model = (mongoose) => {
|
|
147
147
|
username: String,
|
148
148
|
phone: String,
|
149
149
|
email: String,
|
150
|
+
apple_id: String,
|
150
151
|
password: String,
|
152
|
+
status: {
|
153
|
+
type: String,
|
154
|
+
enum: ["active", "banned", "removed"],
|
155
|
+
default: "active",
|
156
|
+
required: true
|
157
|
+
},
|
151
158
|
profile: {
|
152
159
|
photo: {
|
153
160
|
type: String,
|
package/dist/users.server.mjs
CHANGED
@@ -146,7 +146,14 @@ var user_model = (mongoose) => {
|
|
146
146
|
username: String,
|
147
147
|
phone: String,
|
148
148
|
email: String,
|
149
|
+
apple_id: String,
|
149
150
|
password: String,
|
151
|
+
status: {
|
152
|
+
type: String,
|
153
|
+
enum: ["active", "banned", "removed"],
|
154
|
+
default: "active",
|
155
|
+
required: true
|
156
|
+
},
|
150
157
|
profile: {
|
151
158
|
photo: {
|
152
159
|
type: String,
|
package/package.json
CHANGED
@@ -50,12 +50,13 @@
|
|
50
50
|
>
|
51
51
|
{{owner.target.profile.name}}
|
52
52
|
</span>
|
53
|
+
|
53
54
|
<span
|
54
55
|
v-if="!creator.hidden && owner.target.profile.name !== creator.target.profile.name"
|
55
56
|
@click.stop="$router.push({
|
56
57
|
name: 'User Profile',
|
57
58
|
params: {
|
58
|
-
_id:
|
59
|
+
_id: creator.target._id
|
59
60
|
}
|
60
61
|
})"
|
61
62
|
>
|
@@ -12,8 +12,8 @@
|
|
12
12
|
"passwordPlaceholder": "Enter your password",
|
13
13
|
"forgotPassword": "Forgot Password?",
|
14
14
|
"signin": "Sign In",
|
15
|
+
"signin_apple": "Sign In with Apple",
|
15
16
|
"soon": "SOON",
|
16
|
-
"signinMetamask": "Sign In with Apple"
|
17
17
|
},
|
18
18
|
"ru": {
|
19
19
|
"title": "Приветствуем вас,",
|
@@ -27,8 +27,8 @@
|
|
27
27
|
"passwordPlaceholder": "Введите ваш пароль",
|
28
28
|
"forgotPassword": "Забыли пароль?",
|
29
29
|
"signin": "Войти",
|
30
|
-
"
|
31
|
-
"
|
30
|
+
"signin_apple": "Войти через Apple",
|
31
|
+
"soon": "СКОРО"
|
32
32
|
}
|
33
33
|
}
|
34
34
|
</i18n>
|
@@ -105,16 +105,29 @@
|
|
105
105
|
/>
|
106
106
|
<!-- Links -->
|
107
107
|
<div class="w-100 mn-big">
|
108
|
-
<router-link
|
108
|
+
<router-link
|
109
|
+
to="/auth/reset-password"
|
110
|
+
class="underline d-block t-blue"
|
111
|
+
>
|
112
|
+
{{ t('forgotPassword') }}
|
113
|
+
</router-link>
|
109
114
|
</div>
|
110
115
|
<!-- Button -->
|
111
|
-
<Button
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
</
|
116
|
+
<Button
|
117
|
+
:submit="onSubmit"
|
118
|
+
:callback="redirectTo"
|
119
|
+
class="mn-thin"
|
120
|
+
>
|
121
|
+
{{ t('signin') }}
|
122
|
+
</Button>
|
123
|
+
|
124
|
+
<Button
|
125
|
+
:submit="onSubmitApple"
|
126
|
+
:callback="redirectTo"
|
127
|
+
class="mn-thin bg-black t-white"
|
128
|
+
>
|
129
|
+
{{ t('signin_apple') }}
|
130
|
+
</Button>
|
118
131
|
</section>
|
119
132
|
</template>
|
120
133
|
|
@@ -150,37 +163,6 @@ const tabAuth = ref('phone')
|
|
150
163
|
const clientId = inject('APPLE_CLIENTID')
|
151
164
|
const redirectURI = inject('APPLE_REDIRECT_URL')
|
152
165
|
|
153
|
-
const appleSignIn = async () => {
|
154
|
-
|
155
|
-
window.AppleID.auth.init({
|
156
|
-
clientId: clientId,
|
157
|
-
scope: 'email name',
|
158
|
-
redirectURI: redirectURI,
|
159
|
-
usePopup: true,
|
160
|
-
});
|
161
|
-
/** Signin to appleID */
|
162
|
-
return window.AppleID.auth
|
163
|
-
.signIn()
|
164
|
-
.then((response) => {
|
165
|
-
/** This is only called in case usePopup is true */
|
166
|
-
if (onSuccess) {
|
167
|
-
onSuccess(response);
|
168
|
-
}
|
169
|
-
/** resolve with the reponse */
|
170
|
-
return response;
|
171
|
-
})
|
172
|
-
.catch((err) => {
|
173
|
-
if (onError) {
|
174
|
-
/** Call onError catching the error */
|
175
|
-
onError(err);
|
176
|
-
} else {
|
177
|
-
/** Log the error to help debug */
|
178
|
-
console.error(err);
|
179
|
-
}
|
180
|
-
return null;
|
181
|
-
});
|
182
|
-
};
|
183
|
-
|
184
166
|
const loadExternalScript = (src) => {
|
185
167
|
return new Promise((resolve, reject) => {
|
186
168
|
const script = document.createElement('script');
|
@@ -216,6 +198,29 @@ async function onSubmit() {
|
|
216
198
|
await auth.actions.login(auth.state.user, tabAuth.value)
|
217
199
|
}
|
218
200
|
|
201
|
+
async function onSubmitApple() {
|
202
|
+
try {
|
203
|
+
window.AppleID.auth.init({
|
204
|
+
clientId: clientId,
|
205
|
+
scope: 'email name',
|
206
|
+
redirectURI: redirectURI,
|
207
|
+
usePopup: true,
|
208
|
+
});
|
209
|
+
|
210
|
+
let response = await window.AppleID.auth.signIn();
|
211
|
+
|
212
|
+
if (response) {
|
213
|
+
console.log(response);
|
214
|
+
await auth.actions.login(response, 'apple');
|
215
|
+
}
|
216
|
+
|
217
|
+
} catch (error) {
|
218
|
+
console.error(error);
|
219
|
+
throw new Error('Error during Apple authentication');
|
220
|
+
}
|
221
|
+
}
|
222
|
+
|
223
|
+
|
219
224
|
function redirectTo () {
|
220
225
|
router.push({ name: 'User Profile', params: { _id: auth.state.user._id }})
|
221
226
|
}
|
@@ -256,5 +261,4 @@ function redirectTo () {
|
|
256
261
|
border: 1px solid red;
|
257
262
|
box-shadow: 0 0 3px 0 red;
|
258
263
|
}
|
259
|
-
|
260
|
-
</style>
|
264
|
+
</style>
|
@@ -2,17 +2,21 @@ const jwt = require("jsonwebtoken");
|
|
2
2
|
const bcrypt = require("bcryptjs");
|
3
3
|
const ObjectId = require('mongoose').Types.ObjectId;
|
4
4
|
const { uuid } = require('uuidv4');
|
5
|
-
|
5
|
+
// Utils
|
6
|
+
const { verifyAppleIdToken } = require('../utils/server/verifyAppleIdToken')
|
7
|
+
// Factory
|
6
8
|
const controllerFactory = (db) => {
|
9
|
+
|
7
10
|
const User = db.user;
|
8
11
|
const Membership = db.membership;
|
9
12
|
const Invite = db.invite;
|
10
13
|
const Role = db.role;
|
11
14
|
|
12
15
|
const signin = async (req, res) => {
|
13
|
-
const { type, email, phone } = req.body;
|
16
|
+
const { type, email, phone, authorization } = req.body;
|
14
17
|
|
15
18
|
let query;
|
19
|
+
let payload = null;
|
16
20
|
|
17
21
|
if (type === 'phone' && phone) {
|
18
22
|
query = { phone };
|
@@ -22,18 +26,45 @@ const controllerFactory = (db) => {
|
|
22
26
|
query = { email };
|
23
27
|
}
|
24
28
|
|
29
|
+
if (type === 'apple' && authorization.id_token) {
|
30
|
+
|
31
|
+
payload = await verifyAppleIdToken(authorization.id_token);
|
32
|
+
|
33
|
+
if (payload) {
|
34
|
+
query = { apple_id: payload.sub };
|
35
|
+
} else {
|
36
|
+
return res.status(401).send({ errorCode: "INVALID_APPLE_ID_TOKEN" });
|
37
|
+
}
|
38
|
+
}
|
39
|
+
|
25
40
|
try {
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
41
|
+
|
42
|
+
let user = await User.findOne(query).populate('roles').exec();
|
43
|
+
|
44
|
+
if ((type === 'email' || type === 'phone') && req.body.password) {
|
45
|
+
|
46
|
+
const passwordIsValid = bcrypt.compareSync(req.body.password, user.password);
|
47
|
+
|
48
|
+
if (!passwordIsValid) {
|
49
|
+
return res.status(401).send({ errorCode: "INCORRECT_PASSWORD_ENTERED", accessToken: null });
|
50
|
+
}
|
30
51
|
}
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
52
|
+
|
53
|
+
if (type === 'apple' && !user) {
|
54
|
+
const { firstName, lastName } = req.body.user.name;
|
55
|
+
|
56
|
+
const newUser = new User({
|
57
|
+
apple_id: payload.sub,
|
58
|
+
email: payload.email,
|
59
|
+
profile: { name: `${firstName} ${lastName}` },
|
60
|
+
});
|
61
|
+
|
62
|
+
await newUser.save();
|
63
|
+
user = newUser;
|
64
|
+
} else if (!user) {
|
65
|
+
return res.status(404).send({ errorCode: "USER_NOT_FOUND" });
|
36
66
|
}
|
67
|
+
|
37
68
|
const memberships = await Membership.findOne({ user: user._id });
|
38
69
|
|
39
70
|
const token = jwt.sign({
|
@@ -46,21 +46,13 @@
|
|
46
46
|
const actions = {
|
47
47
|
async login (user, type) {
|
48
48
|
try {
|
49
|
-
|
50
|
-
console.log(user.phone.number)
|
51
|
-
|
52
49
|
const response = await $axios.post('/api/auth/signin', {
|
53
|
-
|
54
|
-
phone: user.phone.number,
|
55
|
-
password: user.password,
|
56
|
-
passwordRepeat: '',
|
50
|
+
...user,
|
57
51
|
type
|
58
52
|
})
|
59
53
|
|
60
54
|
setCookie('user', response.data);
|
61
55
|
|
62
|
-
console.log(response.data)
|
63
|
-
|
64
56
|
Object.assign(state.user, {
|
65
57
|
...response.data
|
66
58
|
});
|
@@ -76,7 +68,8 @@
|
|
76
68
|
|
77
69
|
Object.assign(state.access, {
|
78
70
|
token: null,
|
79
|
-
status: false
|
71
|
+
status: false,
|
72
|
+
roles: null
|
80
73
|
});
|
81
74
|
|
82
75
|
setError(error)
|
@@ -0,0 +1,57 @@
|
|
1
|
+
const jwt = require('jsonwebtoken');
|
2
|
+
const fetch = require('node-fetch');
|
3
|
+
const jwkToPem = require('jwk-to-pem');
|
4
|
+
|
5
|
+
async function verifyAppleIdToken(id_token) {
|
6
|
+
// Decode the token (without verification)
|
7
|
+
const decodedToken = jwt.decode(id_token, { complete: true });
|
8
|
+
if (!decodedToken) {
|
9
|
+
throw new Error('Failed to decode token.');
|
10
|
+
}
|
11
|
+
|
12
|
+
// Check iss claim
|
13
|
+
if (decodedToken.payload.iss !== 'https://appleid.apple.com') {
|
14
|
+
throw new Error('Invalid issuer.');
|
15
|
+
}
|
16
|
+
|
17
|
+
// Check aud claim - Replace YOUR_APP_CLIENT_ID with your client ID
|
18
|
+
if (decodedToken.payload.aud !== process.env.APPLE_CLIENTID) {
|
19
|
+
throw new Error('Invalid audience.');
|
20
|
+
}
|
21
|
+
|
22
|
+
// Ensure the token has not expired
|
23
|
+
const currentTimestamp = Math.floor(Date.now() / 1000);
|
24
|
+
if (currentTimestamp > decodedToken.payload.exp) {
|
25
|
+
throw new Error('Token has expired.');
|
26
|
+
}
|
27
|
+
|
28
|
+
// Fetch Apple's public keys
|
29
|
+
const applePublicKeys = await fetch('https://appleid.apple.com/auth/keys')
|
30
|
+
.then(response => response.json())
|
31
|
+
.catch(err => {
|
32
|
+
throw new Error('Failed to fetch Apple public keys.');
|
33
|
+
});
|
34
|
+
|
35
|
+
const appleKey = applePublicKeys.keys.find(key => key.kid === decodedToken.header.kid);
|
36
|
+
if (!appleKey) {
|
37
|
+
throw new Error('Invalid token key ID.');
|
38
|
+
}
|
39
|
+
|
40
|
+
// Convert JWK to PEM
|
41
|
+
const pem = jwkToPem(appleKey);
|
42
|
+
|
43
|
+
// Verify the token's signature using the PEM
|
44
|
+
try {
|
45
|
+
jwt.verify(id_token, pem, {
|
46
|
+
algorithms: ['RS256'],
|
47
|
+
issuer: 'https://appleid.apple.com'
|
48
|
+
});
|
49
|
+
} catch (err) {
|
50
|
+
console.log(err);
|
51
|
+
throw new Error('Token signature verification failed.');
|
52
|
+
}
|
53
|
+
|
54
|
+
return decodedToken.payload; // or return the entire payload, depending on your needs
|
55
|
+
}
|
56
|
+
|
57
|
+
module.exports = { verifyAppleIdToken };
|
@@ -3,6 +3,14 @@
|
|
3
3
|
class="for-transition w-100"
|
4
4
|
>
|
5
5
|
<div
|
6
|
+
v-if="users.state.current.status === 'removed'"
|
7
|
+
class="flex-center flex pd-medium radius-big bg-grey uppercase t-semi w-100 h-100"
|
8
|
+
>
|
9
|
+
Sorry, user has been removed.
|
10
|
+
</div>
|
11
|
+
|
12
|
+
<div
|
13
|
+
v-else
|
6
14
|
_id="dash"
|
7
15
|
class="pd-b-extra pd-thin w-100"
|
8
16
|
>
|
@@ -41,13 +49,19 @@
|
|
41
49
|
<h3
|
42
50
|
class="mn-thin"
|
43
51
|
>
|
44
|
-
{{users.state.current.profile.name ? users.state.current.profile.name : '
|
52
|
+
{{users.state.current.profile.name ? users.state.current.profile.name : 'Not specified' }}
|
45
53
|
</h3>
|
46
54
|
|
47
55
|
<p
|
48
|
-
class="mn-
|
56
|
+
class="mn-thin t-main t-semi"
|
49
57
|
>
|
50
|
-
@{{ users.state.current.username ? users.state.current.username : '
|
58
|
+
@{{ users.state.current.username ? users.state.current.username : 'Not specified' }}
|
59
|
+
</p>
|
60
|
+
|
61
|
+
<p
|
62
|
+
class="mn-small p-medium"
|
63
|
+
>
|
64
|
+
{{ users.state.current.profile.description ? users.state.current.profile.description : 'Not specified' }}
|
51
65
|
</p>
|
52
66
|
|
53
67
|
<div class="mn-medium flex-center flex-nowrap flex">
|
@@ -75,7 +89,7 @@
|
|
75
89
|
:isMember="users.state.current.isMember"
|
76
90
|
:targetId="users.state.current._id"
|
77
91
|
:userId="auth.state.user._id"
|
78
|
-
class="w-min mn-auto"
|
92
|
+
class="w-min mn-medium mn-r-auto mn-l-auto"
|
79
93
|
@updateMembership="handleMembershipUpdate"
|
80
94
|
/>
|
81
95
|
|
@@ -142,8 +156,8 @@
|
|
142
156
|
<span
|
143
157
|
class="t-red"
|
144
158
|
>
|
145
|
-
|
146
|
-
|
159
|
+
Logout
|
160
|
+
</span>
|
147
161
|
</MenuItem>
|
148
162
|
</Menu>
|
149
163
|
|
@@ -12,7 +12,7 @@
|
|
12
12
|
|
13
13
|
<Field
|
14
14
|
v-model:field="user.username"
|
15
|
-
label="
|
15
|
+
label="@"
|
16
16
|
placeholder="Not specified"
|
17
17
|
class="mn-thin w-100 bg-grey pd-medium radius-small"
|
18
18
|
disabled="true"
|
@@ -88,8 +88,6 @@
|
|
88
88
|
/>
|
89
89
|
<!-- -->
|
90
90
|
<h3 class="mn-small">Account</h3>
|
91
|
-
|
92
|
-
<p class="mn-thin">If you want to change your account details please contact the administratior: admin@thecommunephuket.com</p>
|
93
91
|
|
94
92
|
<Field
|
95
93
|
v-model:field="user.phone"
|
@@ -104,12 +102,14 @@
|
|
104
102
|
v-model:field="user.email"
|
105
103
|
label="Email"
|
106
104
|
placeholder="Not specified"
|
107
|
-
class="mn-
|
105
|
+
class="mn-semi bg-grey pd-medium radius-small"
|
108
106
|
:disabled="true"
|
109
107
|
:validation="organizationName"
|
110
108
|
/>
|
111
109
|
|
112
|
-
|
110
|
+
<Button :submit="onSubmit" :callback="redirectTo" class="mn-thin">Save</Button>
|
111
|
+
|
112
|
+
<Button :submit="onSubmitDelete" :callback="a = () => {router.push({name: 'Sign In'})}" class="mn-thin bg-red t-white">Delete Account</Button>
|
113
113
|
</div>
|
114
114
|
</template>
|
115
115
|
|
@@ -141,7 +141,17 @@
|
|
141
141
|
async function onSubmit() {
|
142
142
|
await users.actions.update(users.state.current)
|
143
143
|
}
|
144
|
+
async function onSubmitDelete() {
|
145
|
+
const confirmation = window.confirm("Are you sure you want to delete your account? Restoration will be possible only with the help of an administrator.");
|
146
|
+
|
147
|
+
if (!confirmation) {
|
148
|
+
return;
|
149
|
+
}
|
144
150
|
|
151
|
+
users.state.current.status = 'removed'
|
152
|
+
await users.actions.update(users.state.current)
|
153
|
+
auth.actions.logout()
|
154
|
+
}
|
145
155
|
function redirectTo () {
|
146
156
|
router.replace({ name: 'User Profile', params: { _id: users.state.current._id }});
|
147
157
|
}
|
@@ -5,8 +5,16 @@ module.exports = (mongoose) => {
|
|
5
5
|
|
6
6
|
phone: String,
|
7
7
|
email: String,
|
8
|
+
apple_id: String,
|
8
9
|
password: String,
|
9
|
-
|
10
|
+
|
11
|
+
status: {
|
12
|
+
type: String,
|
13
|
+
enum: ['active','banned','removed'],
|
14
|
+
default: 'active',
|
15
|
+
required: true,
|
16
|
+
},
|
17
|
+
|
10
18
|
profile: {
|
11
19
|
photo: {
|
12
20
|
type: String,
|
@@ -13,6 +13,8 @@ const state = reactive({
|
|
13
13
|
email: "",
|
14
14
|
phone: "",
|
15
15
|
|
16
|
+
status: "",
|
17
|
+
|
16
18
|
profile: {
|
17
19
|
name: "",
|
18
20
|
photo: "",
|
@@ -71,7 +73,6 @@ const actions = {
|
|
71
73
|
},
|
72
74
|
|
73
75
|
async update(user) {
|
74
|
-
console.log(user)
|
75
76
|
try {
|
76
77
|
const response = await $axios.put(`/api/users/${user._id}`, user);
|
77
78
|
mutations.set(response.data, 'current');
|