Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions shatter-backend/docs/API_REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,7 @@ Update a user's profile. Users can only update their own profile.
| `password` | string | Minimum 8 characters |
| `bio` | string | |
| `profilePhoto` | string | URL |
| `socialLinks` | object | `{ linkedin?: string, github?: string, other?: string[] }` — `other` replaces the whole array on update |
| `socialLinks` | object | `{ linkedin?: string, github?: string, other?: Array<{ label: string, url: string }> }` — each `other` entry has a required `label` and `url`; the array fully replaces the previous one on update |
| `organization` | string | Where the user works/studies |
| `title` | string | Job title or role |

Expand Down Expand Up @@ -853,7 +853,7 @@ Join an event as a guest (no account required).
| `socialLinks` | object | No* | Social links |
| `socialLinks.linkedin` | string | No | LinkedIn URL |
| `socialLinks.github` | string | No | GitHub URL |
| `socialLinks.other` | string[] | No | Array of additional social/profile URLs |
| `socialLinks.other` | `Array<{label, url}>` | No | Additional labeled social/profile links. Each entry requires both `label` (display name) and `url`. |
| `organization` | string | No* | Where the guest works/studies |
| `title` | string | No | Job title or role |

Expand Down
2 changes: 1 addition & 1 deletion shatter-backend/docs/DATABASE_SCHEMA.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
| `title` | String | No | — | Trimmed |
| `bio` | String | No | — | Trimmed |
| `profilePhoto` | String | No | — | |
| `socialLinks` | Object | No | — | `{ linkedin?: String, github?: String, other?: String[] }` — `other` is an array so users can add multiple miscellaneous links |
| `socialLinks` | Object | No | — | `{ linkedin?: String, github?: String, other?: Array<{ label: String, url: String }> }` — each `other` entry has a required `label` and `url` so users can add multiple labeled miscellaneous links |
| `authProvider` | String (enum) | Yes | `'local'` | One of: `'local'`, `'linkedin'`, `'guest'` |
| `lastLogin` | Date | No | `null` | |
| `passwordChangedAt`| Date | No | `null` | |
Expand Down
7 changes: 6 additions & 1 deletion shatter-backend/src/controllers/auth_controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,12 @@ export const linkedinCallback = async (req: Request, res: Response) => {
let statePayload: { linking?: boolean; userId?: string };
try {
statePayload = jwt.verify(state, JWT_SECRET) as { linking?: boolean; userId?: string };
} catch {
} catch (e: any) {
console.error('LinkedIn state verify failed:', {
name: e?.name,
message: e?.message,
stateLen: state?.length,
});
return res.status(401).json({ error: 'Invalid state parameter' });
}

Expand Down
4 changes: 2 additions & 2 deletions shatter-backend/src/controllers/event_controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ export async function joinEventAsGuest(req: Request, res: Response) {
const { name, email, socialLinks, organization, title } = req.body as {
name?: string;
email?: string;
socialLinks?: { linkedin?: string; github?: string; other?: string[] };
socialLinks?: { linkedin?: string; github?: string; other?: { label: string; url: string }[] };
organization?: string;
title?: string;
};
Expand All @@ -295,7 +295,7 @@ export async function joinEventAsGuest(req: Request, res: Response) {
const hasSocialLink = socialLinks && (
socialLinks.linkedin?.trim() ||
socialLinks.github?.trim() ||
socialLinks.other?.some((s) => s.trim())
socialLinks.other?.some((entry) => entry?.url?.trim())
);
const hasOrganization = organization && organization.trim();

Expand Down
3 changes: 2 additions & 1 deletion shatter-backend/src/controllers/user_controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ export const updateUser = async (req: Request, res: Response) => {
password?: string;
bio?: string;
profilePhoto?: string;
socialLinks?: { linkedin?: string; github?: string; other?: string[] };
socialLinks?: { linkedin?: string; github?: string; other?: { label: string; url: string }[] };
organization?: string;
title?: string;
};
Expand Down Expand Up @@ -174,6 +174,7 @@ export const updateUser = async (req: Request, res: Response) => {
const result = await User.updateOne(
{ _id: userId },
{ $set: updateFields },
{ runValidators: true },
);

if (result.matchedCount === 0) {
Expand Down
15 changes: 13 additions & 2 deletions shatter-backend/src/models/user_model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export interface IUser {
socialLinks?: {
linkedin?: string;
github?: string;
other?: string[];
other?: { label: string; url: string }[];
};
authProvider: 'local' | 'linkedin' | 'guest';
lastLogin?: Date;
Expand Down Expand Up @@ -85,7 +85,18 @@ const UserSchema = new Schema<IUser>(
socialLinks: {
linkedin: { type: String },
github: { type: String },
other: { type: [String], default: undefined },
other: {
type: [
new Schema(
{
label: { type: String, required: true, trim: true },
url: { type: String, required: true, trim: true },
},
{ _id: false },
),
],
default: undefined,
},
},
authProvider: {
type: String,
Expand Down
Loading