nodebb-plugin-sso-biogrenci 1.0.0 → 1.0.2
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/.claude/settings.local.json +10 -0
- package/image.png +0 -0
- package/library.js +131 -28
- package/package.json +3 -3
- package/plugin.json +5 -0
- package/static/lib/account-biogrenci.js +72 -0
- package/static/lib/admin.js +44 -0
- package/static/lib/biogrenci-firsatlar.js +234 -0
- package/static/style.less +418 -96
- package/static/templates/account/biogrenci.tpl +0 -67
- package/static/templates/admin/plugins/sso-biogrenci.tpl +18 -19
- package/static/templates/biogrenci-firsatlar.tpl +18 -171
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(tree -L 3 -I 'node_modules' /c/Users/kadir/OneDrive/Masaüstü/Projeler/nodebb-plugin-sso-biogrenci/ 2>/dev/null || find /c/Users/kadir/OneDrive/Masaüstü/Projeler/nodebb-plugin-sso-biogrenci -not -path '*/node_modules/*' -type f | sort)",
|
|
5
|
+
"WebFetch(domain:raw.githubusercontent.com)",
|
|
6
|
+
"Bash(xargs grep:*)",
|
|
7
|
+
"WebFetch(domain:biogrenci.com)"
|
|
8
|
+
]
|
|
9
|
+
}
|
|
10
|
+
}
|
package/image.png
ADDED
|
Binary file
|
package/library.js
CHANGED
|
@@ -7,8 +7,11 @@ const user = require.main.require('./src/user');
|
|
|
7
7
|
const db = require.main.require('./src/database');
|
|
8
8
|
const meta = require.main.require('./src/meta');
|
|
9
9
|
const groups = require.main.require('./src/groups');
|
|
10
|
+
const winston = require.main.require('winston');
|
|
10
11
|
const authenticationController = require.main.require('./src/controllers/authentication');
|
|
11
12
|
|
|
13
|
+
const LOG_PREFIX = '[sso-biogrenci]';
|
|
14
|
+
|
|
12
15
|
const constants = {
|
|
13
16
|
name: 'biogrenci',
|
|
14
17
|
displayName: "bi'öğrenci",
|
|
@@ -25,70 +28,91 @@ const plugin = {
|
|
|
25
28
|
clientId: '019ccf3d-0032-70e0-bf69-474e3f4dd2fa',
|
|
26
29
|
clientSecret: '0bpVolqxVtNGcrZuVWtWjNfKr36EABj8zzj61e6i',
|
|
27
30
|
},
|
|
31
|
+
ready: false,
|
|
28
32
|
};
|
|
29
33
|
|
|
30
34
|
plugin.init = async function (params) {
|
|
31
35
|
const { router, middleware } = params;
|
|
36
|
+
winston.info(`${LOG_PREFIX} Initializing plugin...`);
|
|
32
37
|
|
|
33
38
|
// Admin settings page
|
|
34
39
|
router.get('/admin/plugins/sso-biogrenci', middleware.admin.buildHeader, renderAdmin);
|
|
35
40
|
router.get('/api/admin/plugins/sso-biogrenci', renderAdmin);
|
|
41
|
+
winston.info(`${LOG_PREFIX} Admin routes registered`);
|
|
36
42
|
|
|
37
43
|
// Firsatlar (discounts) page
|
|
38
44
|
router.get('/firsatlar', middleware.buildHeader, renderFirsatlar);
|
|
39
45
|
router.get('/api/firsatlar', renderFirsatlar);
|
|
46
|
+
winston.info(`${LOG_PREFIX} Firsatlar routes registered`);
|
|
40
47
|
|
|
41
48
|
// API: fetch opportunities from bi'ogrenci
|
|
42
49
|
router.get('/api/biogrenci/firsatlar', async (req, res) => {
|
|
50
|
+
winston.info(`${LOG_PREFIX} GET /api/biogrenci/firsatlar query=%j`, req.query);
|
|
43
51
|
try {
|
|
44
52
|
const data = await fetchOpportunities(req.query);
|
|
53
|
+
winston.info(`${LOG_PREFIX} Firsatlar response: %d items`, data.data ? data.data.length : 0);
|
|
45
54
|
res.json(data);
|
|
46
55
|
} catch (err) {
|
|
56
|
+
winston.error(`${LOG_PREFIX} Firsatlar fetch error: %s`, err.message);
|
|
47
57
|
res.status(500).json({ error: err.message });
|
|
48
58
|
}
|
|
49
59
|
});
|
|
50
60
|
|
|
51
61
|
// API: claim an opportunity
|
|
52
62
|
router.post('/api/biogrenci/firsatlar/:id/claim', async (req, res) => {
|
|
63
|
+
winston.info(`${LOG_PREFIX} POST claim opportunity id=%s uid=%s`, req.params.id, req.uid);
|
|
53
64
|
if (!req.uid) {
|
|
54
65
|
return res.status(401).json({ error: 'Giriş yapmanız gerekiyor' });
|
|
55
66
|
}
|
|
56
67
|
try {
|
|
57
68
|
const accessToken = await db.getObjectField(`biogrenci:uid:${req.uid}`, 'accessToken');
|
|
58
69
|
if (!accessToken) {
|
|
70
|
+
winston.warn(`${LOG_PREFIX} No access token for uid=%s`, req.uid);
|
|
59
71
|
return res.status(403).json({ error: "bi'öğrenci hesabınızla giriş yapmalısınız" });
|
|
60
72
|
}
|
|
61
|
-
const
|
|
73
|
+
const url = `${constants.partnerAPIBase}/opportunities/${req.params.id}/claim`;
|
|
74
|
+
winston.info(`${LOG_PREFIX} Claiming: POST %s`, url);
|
|
75
|
+
const response = await fetch(url, {
|
|
62
76
|
method: 'POST',
|
|
63
77
|
headers: { Authorization: `Bearer ${accessToken}` },
|
|
64
78
|
});
|
|
65
79
|
const data = await response.json();
|
|
80
|
+
winston.info(`${LOG_PREFIX} Claim response status=%d data=%j`, response.status, data);
|
|
66
81
|
res.json(data);
|
|
67
82
|
} catch (err) {
|
|
83
|
+
winston.error(`${LOG_PREFIX} Claim error: %s`, err.message);
|
|
68
84
|
res.status(500).json({ error: err.message });
|
|
69
85
|
}
|
|
70
86
|
});
|
|
71
87
|
|
|
72
88
|
// Profile: link/unlink bi'öğrenci account
|
|
73
89
|
router.get('/api/biogrenci/status', async (req, res) => {
|
|
90
|
+
winston.verbose(`${LOG_PREFIX} GET /api/biogrenci/status uid=%s`, req.uid);
|
|
74
91
|
if (!req.uid) {
|
|
75
92
|
return res.json({ linked: false });
|
|
76
93
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
94
|
+
try {
|
|
95
|
+
const data = await db.getObject(`biogrenci:uid:${req.uid}`);
|
|
96
|
+
if (data && data.biogrenciId) {
|
|
97
|
+
const education = await user.getUserField(req.uid, 'biogrenci_education');
|
|
98
|
+
const verified = await user.getUserField(req.uid, 'biogrenci_verified');
|
|
99
|
+
winston.verbose(`${LOG_PREFIX} Status: linked=true verified=%s`, !!verified);
|
|
100
|
+
return res.json({
|
|
101
|
+
linked: true,
|
|
102
|
+
biogrenciId: data.biogrenciId,
|
|
103
|
+
education: education || null,
|
|
104
|
+
verified: !!verified,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
res.json({ linked: false });
|
|
108
|
+
} catch (err) {
|
|
109
|
+
winston.error(`${LOG_PREFIX} Status error: %s`, err.message);
|
|
110
|
+
res.json({ linked: false });
|
|
87
111
|
}
|
|
88
|
-
res.json({ linked: false });
|
|
89
112
|
});
|
|
90
113
|
|
|
91
114
|
router.post('/api/biogrenci/unlink', async (req, res) => {
|
|
115
|
+
winston.info(`${LOG_PREFIX} POST /api/biogrenci/unlink uid=%s`, req.uid);
|
|
92
116
|
if (!req.uid) {
|
|
93
117
|
return res.status(401).json({ error: 'Giriş yapmanız gerekiyor' });
|
|
94
118
|
}
|
|
@@ -102,25 +126,44 @@ plugin.init = async function (params) {
|
|
|
102
126
|
await user.setUserField(req.uid, 'biogrenci_education', '');
|
|
103
127
|
await user.setUserField(req.uid, 'biogrenci_verified', false);
|
|
104
128
|
await groups.leave('Doğrulanmış Öğrenciler', req.uid);
|
|
129
|
+
winston.info(`${LOG_PREFIX} Unlinked uid=%s`, req.uid);
|
|
105
130
|
res.json({ success: true });
|
|
106
131
|
} catch (err) {
|
|
132
|
+
winston.error(`${LOG_PREFIX} Unlink error: %s`, err.message);
|
|
107
133
|
res.status(500).json({ error: err.message });
|
|
108
134
|
}
|
|
109
135
|
});
|
|
110
136
|
|
|
111
137
|
// Load settings from DB
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
138
|
+
try {
|
|
139
|
+
const settings = await meta.settings.get('sso-biogrenci');
|
|
140
|
+
winston.info(`${LOG_PREFIX} Loaded settings from DB: clientId=%s clientSecret=%s`,
|
|
141
|
+
settings.clientId ? settings.clientId.substring(0, 8) + '...' : '(empty)',
|
|
142
|
+
settings.clientSecret ? '***set***' : '(empty)'
|
|
143
|
+
);
|
|
144
|
+
if (settings.clientId) plugin.settings.clientId = settings.clientId;
|
|
145
|
+
if (settings.clientSecret) plugin.settings.clientSecret = settings.clientSecret;
|
|
146
|
+
} catch (err) {
|
|
147
|
+
winston.error(`${LOG_PREFIX} Failed to load settings: %s`, err.message);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
plugin.ready = true;
|
|
151
|
+
winston.info(`${LOG_PREFIX} Plugin initialized. clientId=%s`,
|
|
152
|
+
plugin.settings.clientId ? plugin.settings.clientId.substring(0, 8) + '...' : '(not set)'
|
|
153
|
+
);
|
|
115
154
|
};
|
|
116
155
|
|
|
117
156
|
async function renderAdmin(req, res) {
|
|
157
|
+
const callbackURL = nconf.get('url') + '/auth/biogrenci/callback';
|
|
158
|
+
winston.verbose(`${LOG_PREFIX} Rendering admin page, callbackURL=%s`, callbackURL);
|
|
118
159
|
res.render('admin/plugins/sso-biogrenci', {
|
|
119
160
|
title: "bi'öğrenci SSO",
|
|
161
|
+
callbackURL: callbackURL,
|
|
120
162
|
});
|
|
121
163
|
}
|
|
122
164
|
|
|
123
165
|
async function renderFirsatlar(req, res) {
|
|
166
|
+
winston.verbose(`${LOG_PREFIX} Rendering firsatlar page, uid=%s`, req.uid);
|
|
124
167
|
res.render('biogrenci-firsatlar', {
|
|
125
168
|
title: 'Öğrenci Fırsatları',
|
|
126
169
|
uid: req.uid || 0,
|
|
@@ -137,19 +180,42 @@ async function fetchOpportunities(query) {
|
|
|
137
180
|
params.set('page', query.page || 1);
|
|
138
181
|
params.set('per_page', query.per_page || 20);
|
|
139
182
|
|
|
140
|
-
const
|
|
183
|
+
const url = `${constants.partnerAPIBase}/opportunities?${params.toString()}`;
|
|
184
|
+
winston.info(`${LOG_PREFIX} Fetching opportunities: GET %s`, url);
|
|
185
|
+
|
|
186
|
+
const response = await fetch(url, {
|
|
187
|
+
headers: {
|
|
188
|
+
'Accept': 'application/json',
|
|
189
|
+
'X-Client-Id': plugin.settings.clientId,
|
|
190
|
+
},
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
winston.info(`${LOG_PREFIX} Partner API response: status=%d`, response.status);
|
|
194
|
+
|
|
141
195
|
if (!response.ok) {
|
|
196
|
+
const body = await response.text();
|
|
197
|
+
winston.error(`${LOG_PREFIX} Partner API error: status=%d body=%s`, response.status, body);
|
|
142
198
|
throw new Error(`Partner API error: ${response.status}`);
|
|
143
199
|
}
|
|
144
|
-
|
|
200
|
+
|
|
201
|
+
const data = await response.json();
|
|
202
|
+
winston.info(`${LOG_PREFIX} Partner API data keys=%j`, Object.keys(data));
|
|
203
|
+
return data;
|
|
145
204
|
}
|
|
146
205
|
|
|
147
206
|
plugin.getStrategy = async function (strategies) {
|
|
207
|
+
winston.info(`${LOG_PREFIX} getStrategy called. clientId=%s clientSecret=%s`,
|
|
208
|
+
plugin.settings.clientId ? 'set' : 'NOT SET',
|
|
209
|
+
plugin.settings.clientSecret ? 'set' : 'NOT SET'
|
|
210
|
+
);
|
|
211
|
+
|
|
148
212
|
if (!plugin.settings.clientId || !plugin.settings.clientSecret) {
|
|
213
|
+
winston.warn(`${LOG_PREFIX} Missing credentials, skipping strategy registration`);
|
|
149
214
|
return strategies;
|
|
150
215
|
}
|
|
151
216
|
|
|
152
217
|
const callbackURL = nconf.get('url') + '/auth/biogrenci/callback';
|
|
218
|
+
winston.info(`${LOG_PREFIX} Registering OAuth2 strategy, callbackURL=%s`, callbackURL);
|
|
153
219
|
|
|
154
220
|
const strategy = new OAuth2Strategy(
|
|
155
221
|
{
|
|
@@ -162,19 +228,36 @@ plugin.getStrategy = async function (strategies) {
|
|
|
162
228
|
passReqToCallback: true,
|
|
163
229
|
},
|
|
164
230
|
async (req, accessToken, refreshToken, params, profile, done) => {
|
|
231
|
+
winston.info(`${LOG_PREFIX} OAuth2 callback received. accessToken=%s refreshToken=%s`,
|
|
232
|
+
accessToken ? accessToken.substring(0, 10) + '...' : 'none',
|
|
233
|
+
refreshToken ? 'set' : 'none'
|
|
234
|
+
);
|
|
165
235
|
try {
|
|
166
236
|
// Fetch user info from bi'ogrenci
|
|
237
|
+
winston.info(`${LOG_PREFIX} Fetching userinfo from %s`, constants.userInfoURL);
|
|
167
238
|
const response = await fetch(constants.userInfoURL, {
|
|
168
239
|
headers: { Authorization: `Bearer ${accessToken}` },
|
|
169
240
|
});
|
|
170
241
|
|
|
242
|
+
winston.info(`${LOG_PREFIX} Userinfo response status=%d`, response.status);
|
|
243
|
+
|
|
171
244
|
if (!response.ok) {
|
|
245
|
+
const body = await response.text();
|
|
246
|
+
winston.error(`${LOG_PREFIX} Userinfo error: %s`, body);
|
|
172
247
|
return done(new Error('Kullanıcı bilgisi alınamadı'));
|
|
173
248
|
}
|
|
174
249
|
|
|
175
250
|
const biogrenciUser = await response.json();
|
|
251
|
+
winston.info(`${LOG_PREFIX} Userinfo: sub=%s email=%s name=%s verified=%s`,
|
|
252
|
+
biogrenciUser.sub,
|
|
253
|
+
biogrenciUser.email,
|
|
254
|
+
biogrenciUser.name || biogrenciUser.first_name,
|
|
255
|
+
biogrenciUser.student_verified
|
|
256
|
+
);
|
|
176
257
|
|
|
177
258
|
const handleUser = async function (uid) {
|
|
259
|
+
winston.info(`${LOG_PREFIX} handleUser uid=%s biogrenciId=%s`, uid, biogrenciUser.sub);
|
|
260
|
+
|
|
178
261
|
// Store access/refresh tokens
|
|
179
262
|
await db.setObject(`biogrenci:uid:${uid}`, {
|
|
180
263
|
accessToken,
|
|
@@ -189,14 +272,13 @@ plugin.getStrategy = async function (strategies) {
|
|
|
189
272
|
.filter(Boolean)
|
|
190
273
|
.join(' - ');
|
|
191
274
|
await user.setUserField(uid, 'biogrenci_education', eduString);
|
|
275
|
+
winston.info(`${LOG_PREFIX} Saved education: %s`, eduString);
|
|
192
276
|
}
|
|
193
277
|
|
|
194
278
|
if (biogrenciUser.student_verified) {
|
|
195
279
|
await user.setUserField(uid, 'biogrenci_verified', true);
|
|
196
|
-
}
|
|
197
280
|
|
|
198
|
-
|
|
199
|
-
if (biogrenciUser.student_verified) {
|
|
281
|
+
// Add verified students to a group
|
|
200
282
|
const groupExists = await groups.exists('Doğrulanmış Öğrenciler');
|
|
201
283
|
if (!groupExists) {
|
|
202
284
|
await groups.create({
|
|
@@ -206,8 +288,10 @@ plugin.getStrategy = async function (strategies) {
|
|
|
206
288
|
private: 1,
|
|
207
289
|
disableJoinRequests: 1,
|
|
208
290
|
});
|
|
291
|
+
winston.info(`${LOG_PREFIX} Created "Doğrulanmış Öğrenciler" group`);
|
|
209
292
|
}
|
|
210
293
|
await groups.join('Doğrulanmış Öğrenciler', uid);
|
|
294
|
+
winston.info(`${LOG_PREFIX} User uid=%s added to verified group`, uid);
|
|
211
295
|
}
|
|
212
296
|
|
|
213
297
|
done(null, uid);
|
|
@@ -216,11 +300,13 @@ plugin.getStrategy = async function (strategies) {
|
|
|
216
300
|
// Check if user already linked
|
|
217
301
|
const existingUid = await plugin.getUidByBiogrenciId(biogrenciUser.sub);
|
|
218
302
|
if (existingUid) {
|
|
303
|
+
winston.info(`${LOG_PREFIX} Found existing linked user uid=%s`, existingUid);
|
|
219
304
|
return handleUser(existingUid);
|
|
220
305
|
}
|
|
221
306
|
|
|
222
307
|
// Check if logged-in user wants to link account
|
|
223
308
|
if (req.uid) {
|
|
309
|
+
winston.info(`${LOG_PREFIX} Linking to logged-in user uid=%s`, req.uid);
|
|
224
310
|
await plugin.linkAccount(req.uid, biogrenciUser.sub);
|
|
225
311
|
return handleUser(req.uid);
|
|
226
312
|
}
|
|
@@ -229,30 +315,39 @@ plugin.getStrategy = async function (strategies) {
|
|
|
229
315
|
if (biogrenciUser.email) {
|
|
230
316
|
const existingEmailUid = await user.getUidByEmail(biogrenciUser.email);
|
|
231
317
|
if (existingEmailUid) {
|
|
318
|
+
winston.info(`${LOG_PREFIX} Found user by email uid=%s`, existingEmailUid);
|
|
232
319
|
await plugin.linkAccount(existingEmailUid, biogrenciUser.sub);
|
|
233
320
|
return handleUser(existingEmailUid);
|
|
234
321
|
}
|
|
235
322
|
}
|
|
236
323
|
|
|
237
324
|
// Create new user
|
|
325
|
+
const username = biogrenciUser.first_name
|
|
326
|
+
? `${biogrenciUser.first_name}${biogrenciUser.last_name ? '_' + biogrenciUser.last_name : ''}`
|
|
327
|
+
: `biogrenci_${biogrenciUser.sub}`;
|
|
328
|
+
|
|
329
|
+
winston.info(`${LOG_PREFIX} Creating new user: username=%s email=%s`, username, biogrenciUser.email);
|
|
330
|
+
|
|
238
331
|
const newUid = await user.create({
|
|
239
|
-
username:
|
|
240
|
-
? `${biogrenciUser.first_name}${biogrenciUser.last_name ? '_' + biogrenciUser.last_name : ''}`
|
|
241
|
-
: `biogrenci_${biogrenciUser.sub}`,
|
|
332
|
+
username: username,
|
|
242
333
|
email: biogrenciUser.email || undefined,
|
|
243
334
|
fullname: biogrenciUser.name || undefined,
|
|
244
335
|
});
|
|
245
336
|
|
|
337
|
+
winston.info(`${LOG_PREFIX} Created user uid=%s`, newUid);
|
|
338
|
+
|
|
246
339
|
await plugin.linkAccount(newUid, biogrenciUser.sub);
|
|
247
340
|
|
|
248
341
|
// Set avatar if available
|
|
249
342
|
if (biogrenciUser.avatar) {
|
|
250
343
|
await user.setUserField(newUid, 'picture', biogrenciUser.avatar);
|
|
251
344
|
await user.setUserField(newUid, 'uploadedpicture', biogrenciUser.avatar);
|
|
345
|
+
winston.info(`${LOG_PREFIX} Set avatar for uid=%s`, newUid);
|
|
252
346
|
}
|
|
253
347
|
|
|
254
348
|
handleUser(newUid);
|
|
255
349
|
} catch (err) {
|
|
350
|
+
winston.error(`${LOG_PREFIX} OAuth2 callback error: %s\n%s`, err.message, err.stack);
|
|
256
351
|
done(err);
|
|
257
352
|
}
|
|
258
353
|
},
|
|
@@ -263,6 +358,7 @@ plugin.getStrategy = async function (strategies) {
|
|
|
263
358
|
};
|
|
264
359
|
|
|
265
360
|
passport.use(constants.name, strategy);
|
|
361
|
+
winston.info(`${LOG_PREFIX} Passport strategy "%s" registered`, constants.name);
|
|
266
362
|
|
|
267
363
|
strategies.push({
|
|
268
364
|
name: constants.name,
|
|
@@ -274,15 +370,21 @@ plugin.getStrategy = async function (strategies) {
|
|
|
274
370
|
scope: constants.scope,
|
|
275
371
|
});
|
|
276
372
|
|
|
373
|
+
winston.info(`${LOG_PREFIX} Strategy added to list. Total strategies: %d`, strategies.length);
|
|
277
374
|
return strategies;
|
|
278
375
|
};
|
|
279
376
|
|
|
280
377
|
plugin.listStrategy = async function (strategies) {
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
378
|
+
if (plugin.settings.clientId && plugin.settings.clientSecret) {
|
|
379
|
+
strategies.push({
|
|
380
|
+
name: constants.name,
|
|
381
|
+
displayName: constants.displayName,
|
|
382
|
+
icon: constants.icon,
|
|
383
|
+
});
|
|
384
|
+
winston.verbose(`${LOG_PREFIX} listStrategy: added to list`);
|
|
385
|
+
} else {
|
|
386
|
+
winston.warn(`${LOG_PREFIX} listStrategy: skipped, no credentials`);
|
|
387
|
+
}
|
|
286
388
|
return strategies;
|
|
287
389
|
};
|
|
288
390
|
|
|
@@ -315,6 +417,7 @@ plugin.addCustomFields = async function (data) {
|
|
|
315
417
|
};
|
|
316
418
|
|
|
317
419
|
plugin.linkAccount = async function (uid, biogrenciId) {
|
|
420
|
+
winston.info(`${LOG_PREFIX} Linking uid=%s to biogrenciId=%s`, uid, biogrenciId);
|
|
318
421
|
await db.setObjectField('biogrenci:id', biogrenciId, uid);
|
|
319
422
|
await db.setObjectField(`user:${uid}:biogrenci`, 'biogrenciId', biogrenciId);
|
|
320
423
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nodebb-plugin-sso-biogrenci",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "bi'öğrenci OAuth2 SSO login & öğrenci indirimleri for NodeBB",
|
|
5
5
|
"main": "library.js",
|
|
6
6
|
"keywords": [
|
|
@@ -11,10 +11,10 @@
|
|
|
11
11
|
"oauth2"
|
|
12
12
|
],
|
|
13
13
|
"nbbpm": {
|
|
14
|
-
"compatibility": "^3.2.0"
|
|
14
|
+
"compatibility": "^3.2.0 || ^4.0.0"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"passport-oauth2": "^1.8.0"
|
|
18
18
|
},
|
|
19
19
|
"license": "MIT"
|
|
20
|
-
}
|
|
20
|
+
}
|
package/plugin.json
CHANGED
|
@@ -6,6 +6,11 @@
|
|
|
6
6
|
"static": "./static"
|
|
7
7
|
},
|
|
8
8
|
"less": ["static/style.less"],
|
|
9
|
+
"modules": {
|
|
10
|
+
"../admin/plugins/sso-biogrenci.js": "static/lib/admin.js",
|
|
11
|
+
"../client/biogrenci-firsatlar.js": "static/lib/biogrenci-firsatlar.js",
|
|
12
|
+
"../client/account/biogrenci.js": "static/lib/account-biogrenci.js"
|
|
13
|
+
},
|
|
9
14
|
"hooks": [
|
|
10
15
|
{ "hook": "filter:auth.init", "method": "getStrategy" },
|
|
11
16
|
{ "hook": "filter:auth.list", "method": "listStrategy" },
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
define('forum/account/biogrenci', ['alerts'], function (alerts) {
|
|
4
|
+
var AccountPage = {};
|
|
5
|
+
|
|
6
|
+
AccountPage.init = function () {
|
|
7
|
+
loadStatus();
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
function loadStatus() {
|
|
11
|
+
fetch(config.relative_path + '/api/biogrenci/status')
|
|
12
|
+
.then(function (r) { return r.json(); })
|
|
13
|
+
.then(function (data) {
|
|
14
|
+
var $el = $('#biogrenci-status');
|
|
15
|
+
if (data.linked) {
|
|
16
|
+
$el.html(
|
|
17
|
+
'<div class="biogrenci-linked">' +
|
|
18
|
+
'<div class="biogrenci-linked-badge">' +
|
|
19
|
+
'<i class="fa fa-check-circle"></i> Hesap Bağlı' +
|
|
20
|
+
'</div>' +
|
|
21
|
+
(data.verified
|
|
22
|
+
? '<div class="biogrenci-verified-badge"><i class="fa fa-shield"></i> Doğrulanmış Öğrenci</div>'
|
|
23
|
+
: '') +
|
|
24
|
+
(data.education
|
|
25
|
+
? '<div class="biogrenci-education"><i class="fa fa-university"></i> ' + data.education + '</div>'
|
|
26
|
+
: '') +
|
|
27
|
+
'<hr/>' +
|
|
28
|
+
'<button id="biogrenci-unlink" class="btn btn-danger btn-sm">' +
|
|
29
|
+
'<i class="fa fa-unlink"></i> Bağlantıyı Kaldır' +
|
|
30
|
+
'</button>' +
|
|
31
|
+
'</div>'
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
$('#biogrenci-unlink').on('click', unlinkAccount);
|
|
35
|
+
} else {
|
|
36
|
+
$el.html(
|
|
37
|
+
'<div class="biogrenci-not-linked">' +
|
|
38
|
+
'<p>bi\'öğrenci hesabınız henüz bağlı değil.</p>' +
|
|
39
|
+
'<p class="text-muted">Hesabınızı bağlayarak öğrenci doğrulaması yapabilir ve fırsatlardan yararlanabilirsiniz.</p>' +
|
|
40
|
+
'<a href="' + config.relative_path + '/auth/biogrenci" class="btn btn-primary">' +
|
|
41
|
+
'<i class="fa fa-graduation-cap"></i> bi\'öğrenci Hesabını Bağla' +
|
|
42
|
+
'</a>' +
|
|
43
|
+
'</div>'
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function unlinkAccount() {
|
|
50
|
+
bootbox.confirm("bi'öğrenci hesap bağlantısını kaldırmak istediğinize emin misiniz?", function (ok) {
|
|
51
|
+
if (!ok) return;
|
|
52
|
+
fetch(config.relative_path + '/api/biogrenci/unlink', {
|
|
53
|
+
method: 'POST',
|
|
54
|
+
headers: {
|
|
55
|
+
'x-csrf-token': config.csrf_token,
|
|
56
|
+
'Content-Type': 'application/json',
|
|
57
|
+
},
|
|
58
|
+
})
|
|
59
|
+
.then(function (r) { return r.json(); })
|
|
60
|
+
.then(function (res) {
|
|
61
|
+
if (res.success) {
|
|
62
|
+
alerts.success("bi'öğrenci bağlantısı kaldırıldı");
|
|
63
|
+
loadStatus();
|
|
64
|
+
} else {
|
|
65
|
+
alerts.error(res.error || 'Bir hata oluştu');
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return AccountPage;
|
|
72
|
+
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
define('admin/plugins/sso-biogrenci', ['settings'], function (Settings) {
|
|
4
|
+
var ACP = {};
|
|
5
|
+
|
|
6
|
+
ACP.init = function () {
|
|
7
|
+
console.log('[sso-biogrenci] Admin page init');
|
|
8
|
+
|
|
9
|
+
var $form = $('.sso-biogrenci-settings');
|
|
10
|
+
console.log('[sso-biogrenci] Form element found:', $form.length > 0);
|
|
11
|
+
console.log('[sso-biogrenci] Form inputs:', $form.find('input').length);
|
|
12
|
+
|
|
13
|
+
Settings.load('sso-biogrenci', $form, function () {
|
|
14
|
+
console.log('[sso-biogrenci] Settings loaded from DB');
|
|
15
|
+
console.log('[sso-biogrenci] clientId value:', $('#clientId').val() ? 'set (' + $('#clientId').val().substring(0, 8) + '...)' : '(empty)');
|
|
16
|
+
console.log('[sso-biogrenci] clientSecret value:', $('#clientSecret').val() ? 'set (hidden)' : '(empty)');
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
$('#save').on('click', function () {
|
|
20
|
+
console.log('[sso-biogrenci] Save clicked');
|
|
21
|
+
console.log('[sso-biogrenci] Saving clientId:', $('#clientId').val() ? 'set' : '(empty)');
|
|
22
|
+
console.log('[sso-biogrenci] Saving clientSecret:', $('#clientSecret').val() ? 'set' : '(empty)');
|
|
23
|
+
|
|
24
|
+
Settings.save('sso-biogrenci', $form, function () {
|
|
25
|
+
console.log('[sso-biogrenci] Settings saved successfully');
|
|
26
|
+
app.alertSuccess('Ayarlar kaydedildi!');
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
$('#toggleSecret').on('click', function () {
|
|
31
|
+
var $input = $('#clientSecret');
|
|
32
|
+
var $icon = $(this).find('i');
|
|
33
|
+
if ($input.attr('type') === 'password') {
|
|
34
|
+
$input.attr('type', 'text');
|
|
35
|
+
$icon.removeClass('fa-eye').addClass('fa-eye-slash');
|
|
36
|
+
} else {
|
|
37
|
+
$input.attr('type', 'password');
|
|
38
|
+
$icon.removeClass('fa-eye-slash').addClass('fa-eye');
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
return ACP;
|
|
44
|
+
});
|