-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathusers.js
More file actions
65 lines (56 loc) · 2.19 KB
/
Copy pathusers.js
File metadata and controls
65 lines (56 loc) · 2.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/**
* User bookkeeping: one row per student in `users`, recording when we first saw
* them sign in, plus a per-school tally in `school_counts`.
*/
import supabase from './database.js';
/**
* Record that `username` just signed in, and report when they FIRST did.
*
* A returning user's `firstLoggedIn` is never rewritten — only mutable profile
* fields (school, name) are refreshed — so the timestamp keeps meaning "first
* ever seen" rather than "seen most recently".
*
* @returns {Promise<{firstLoggedIn: string|null}>}
*/
async function recordLogin(username, school, name) {
// username isn't unique in the schema; take the earliest row, which is the
// real first login.
const { data: existing, error: lookupError } = await supabase
.from('users')
.select('firstLoggedIn')
.eq('username', username)
.order('firstLoggedIn', { ascending: true, nullsFirst: true })
.limit(1);
if (lookupError) throw lookupError;
if (existing && existing.length > 0) {
const fields = {};
if (school) fields.school = school;
if (name) fields.name = name;
if (Object.keys(fields).length) {
const { error: updateError } = await supabase
.from('users')
.update(fields)
.eq('username', username);
// Refreshing profile fields is best-effort; failing it shouldn't cost the
// caller their student info.
if (updateError) console.error('Failed to update existing user fields:', updateError);
}
return { firstLoggedIn: existing[0].firstLoggedIn };
}
// `school` is NOT NULL, so a scrape that didn't find one can't create a row.
if (!school) return { firstLoggedIn: null };
// `firstLoggedIn` is deliberately omitted so the column default (now()) fills
// it: the timestamp then comes from the database clock rather than from
// whichever API instance happened to serve the request.
const { data: inserted, error } = await supabase
.from('users')
.insert([{ username, school, name: name || null }])
.select('firstLoggedIn')
.single();
if (error) throw error;
// `school_counts` is kept in sync by a database trigger on `users`.
return { firstLoggedIn: inserted.firstLoggedIn };
}
export {
recordLogin
};