File size: 4,740 Bytes
2fe81ea
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
import { Request, Response } from 'express';
import bcrypt from 'bcryptjs';
import jwt from 'jsonwebtoken';
import { AppDataSource } from '../config/database';
import { User } from '../entities/User';
import { CreatorProfile } from '../entities/CreatorProfile';

const userRepository = AppDataSource.getRepository(User);
const profileRepository = AppDataSource.getRepository(CreatorProfile);

export class CreatorAuthController {
  async register(req: Request, res: Response) {
    try {
      const {
        fullName,
        username,
        email,
        password,
        profileImage,
        bio,
        organization,
        role,
        website,
        linkedinUrl,
        githubUrl,
        huggingfaceUrl,
        primaryLanguages,
        frameworks,
        agentSpecialties,
        preferredCompute,
        endpointHosting,
        walletAddress,
        bankAccount,
        preferredCurrency,
        country,
        taxId,
        idDocumentUrl,
      } = req.body;

      if (!fullName || !username || !email || !password) {
        return res.status(400).json({ error: 'fullName, username, email and password are required' });
      }

      // Username stored without leading @
      const cleanUsername = String(username).replace(/^@+/, '').toLowerCase();

      // Uniqueness checks
      const existingUser = await userRepository.findOne({ where: { email } });
      if (existingUser) return res.status(400).json({ error: 'Email already in use' });
      const existingProfile = await profileRepository.findOne({ where: { username: cleanUsername } });
      if (existingProfile) return res.status(400).json({ error: 'Username already in use' });

      const hashedPassword = await bcrypt.hash(password, 10);

      // Create user
      const user = userRepository.create({ email, password: hashedPassword, name: fullName, isCreator: true, isAdmin: false });
      const savedUser = await userRepository.save(user);

      // Normalize arrays
      const normArray = (v: any) => {
        if (!v) return [] as string[];
        if (Array.isArray(v)) return v;
        try { return JSON.parse(v); } catch { return [String(v)]; }
      };

      // Create profile
      const profile = profileRepository.create({
        userId: savedUser.id,
        fullName,
        username: cleanUsername,
        profileImage,
        bio,
        organization,
        role,
        website,
        linkedinUrl,
        githubUrl,
        huggingfaceUrl,
        primaryLanguages: normArray(primaryLanguages),
        frameworks: normArray(frameworks),
        agentSpecialties: normArray(agentSpecialties),
        preferredCompute,
        endpointHosting,
        walletAddress,
        bankAccount: bankAccount ? (typeof bankAccount === 'string' ? JSON.parse(bankAccount) : bankAccount) : undefined,
        preferredCurrency,
        country,
        taxId,
        idDocumentUrl,
      });
      await profileRepository.save(profile);

      // Token
      const token = jwt.sign(
        { id: savedUser.id, email: savedUser.email, isAdmin: savedUser.isAdmin },
        process.env.JWT_SECRET!,
        { expiresIn: '7d' }
      );

      res.status(201).json({ token, user: { id: savedUser.id, email: savedUser.email, name: savedUser.name, isCreator: true } });
    } catch (error: any) {
      console.error('Creator register error:', error);
      res.status(500).json({ error: error.message || 'Failed to register creator' });
    }
  }

  async login(req: Request, res: Response) {
    try {
      const { email, password } = req.body;
      if (!email || !password) return res.status(400).json({ error: 'Email and password are required' });

      const user = await userRepository.findOne({ where: { email } });
      if (!user || !user.isCreator) return res.status(401).json({ error: 'Invalid credentials' });

      const isValid = await bcrypt.compare(password, user.password);
      if (!isValid) return res.status(401).json({ error: 'Invalid credentials' });

      const token = jwt.sign(
        { id: user.id, email: user.email, isAdmin: user.isAdmin },
        process.env.JWT_SECRET!,
        { expiresIn: '7d' }
      );

      // Fetch profile brief
      const profile = await profileRepository.findOne({ where: { userId: user.id } });

      res.json({
        token,
        user: {
          id: user.id,
          email: user.email,
          name: user.name,
          isCreator: user.isCreator,
          profile: profile ? { username: profile.username, fullName: profile.fullName } : null,
        },
      });
    } catch (error: any) {
      console.error('Creator login error:', error);
      res.status(500).json({ error: error.message || 'Failed to login creator' });
    }
  }
}