This commit is contained in:
Drake Marino 2024-06-06 21:55:56 -05:00
parent ee8b419887
commit 68edb2c3a1
2 changed files with 69 additions and 94 deletions

View File

@ -8,8 +8,8 @@ services:
volumes:
- /var/jenkins_home/logos:/root/FBLA24/fbla-api/logos
environment:
- POSTGRES_USERNAME
- POSTGRES_PASSWORD
- SECRET_KEY
- POSTGRES_ADDRESS
- POSTGRES_PORT
- JOBLINK_POSTGRES_USERNAME
- JOBLINK_POSTGRES_PASSWORD
- JOBLINK_SECRET_KEY
- JOBLINK_POSTGRES_ADDRESS
- JOBLINK_POSTGRES_PORT

View File

@ -2,14 +2,14 @@ import 'dart:convert';
import 'dart:io';
import 'dart:math';
import 'dart:typed_data';
import 'package:argon2/argon2.dart';
import 'package:dart_jsonwebtoken/dart_jsonwebtoken.dart';
import 'package:http/http.dart' as http;
import 'package:postgres/postgres.dart';
import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart' as io;
import 'package:shelf_router/shelf_router.dart';
import 'package:http/http.dart' as http;
import 'package:argon2/argon2.dart';
SecretKey secretKey = SecretKey(Platform.environment['JOBLINK_SECRET_KEY']!);
@ -75,8 +75,7 @@ class Business {
}
Future<String> fetchBusinessData() async {
final result = await postgres.query(
'''
final result = await postgres.query('''
SELECT json_agg(
json_build_object(
'id', id,
@ -92,8 +91,7 @@ Future<String> fetchBusinessData() async {
'locationAddress', "locationAddress"
)
) FROM businesses
'''
);
''');
var encoded = json.encode(result);
var decoded = json.decode(encoded);
@ -105,7 +103,6 @@ Future<String> fetchBusinessData() async {
String _hostname = 'localhost';
const _port = 8000;
final postgres = PostgreSQLConnection(
Platform.environment['JOBLINK_POSTGRES_ADDRESS']!,
int.parse(Platform.environment['JOBLINK_POSTGRES_PORT']!),
@ -114,8 +111,6 @@ final postgres = PostgreSQLConnection(
password: Platform.environment['JOBLINK_POSTGRES_PASSWORD'],
);
void main() async {
await postgres.open();
@ -126,8 +121,8 @@ void main() async {
print('Hello received');
return Response.ok(
'Hello, World!',
headers: {'Access-Control-Allow-Origin': '*'},
'Hello, World!',
headers: {'Access-Control-Allow-Origin': '*'},
);
});
app.get('/fbla-api/businessdata', (Request request) async {
@ -162,15 +157,12 @@ void main() async {
var json = jsonDecode(payload);
Business business = Business.fromJson(json);
await postgres.query(
'''
await postgres.query('''
INSERT INTO businesses (name, description, type, website, "contactName", "contactPhone", "contactEmail", notes, "locationName", "locationAddress")
VALUES ('${business.name.replaceAll("'", "''")}', '${business.description.replaceAll("'", "''")}', '${business.type.name}', '${business.website}', '${business.contactName.replaceAll("'", "''")}', '${business.contactPhone}', '${business.contactEmail}', '${business.notes.replaceAll("'", "''")}', '${business.locationName.replaceAll("'", "''")}', '${business.locationAddress.replaceAll("'", "''")}')
'''
);
''');
final dbBusiness = await postgres.query(
'''SELECT * FROM public.businesses
final dbBusiness = await postgres.query('''SELECT * FROM public.businesses
ORDER BY id DESC LIMIT 1''');
var id = dbBusiness[0][0];
var logoResponse = await http.get(
@ -181,8 +173,8 @@ void main() async {
await File('logos/$id.png').writeAsBytes(logoResponse.bodyBytes);
}
return Response.ok(
id.toString(),
headers: {'Access-Control-Allow-Origin': '*'},
id.toString(),
headers: {'Access-Control-Allow-Origin': '*'},
);
} on JWTExpiredException {
print('JWT Expired');
@ -191,14 +183,13 @@ void main() async {
}
return Response.unauthorized(
'unauthorized',
headers: {'Access-Control-Allow-Origin': '*'},
'unauthorized',
headers: {'Access-Control-Allow-Origin': '*'},
);
});
app.post('/fbla-api/deletebusiness', (Request request) async {
print('delete business request received');
final payload = await request.readAsString();
var auth = request.headers['Authorization']?.replaceAll('Bearer ', '');
try {
@ -206,33 +197,31 @@ void main() async {
var json = jsonDecode(payload);
var id = json['id'];
await postgres.query(
'''
await postgres.query('''
DELETE FROM public.businesses
WHERE id IN
($id);
'''
);
''');
try{
await File('logos/$id.png').delete();
} catch(e) {
try {
await File('logos/$id.png').delete();
} catch (e) {
print('Failure to delete logo! $e');
}
return Response.ok(
id.toString(),
headers: {'Access-Control-Allow-Origin': '*'},
id.toString(),
headers: {'Access-Control-Allow-Origin': '*'},
);
} on JWTExpiredException {
print('JWT Expired');
print('JWT Expired');
} on JWTException catch (e) {
print(e.message);
}
return Response.unauthorized(
'unauthorized',
headers: {'Access-Control-Allow-Origin': '*'},
'unauthorized',
headers: {'Access-Control-Allow-Origin': '*'},
);
});
app.post('/fbla-api/editbusiness', (Request request) async {
@ -246,13 +235,11 @@ void main() async {
var json = jsonDecode(payload);
Business business = Business.fromJson(json);
await postgres.query(
'''
await postgres.query('''
UPDATE businesses SET
name = '${business.name.replaceAll("'", "''").replaceAll("\"", "\"\"")}'::text, description = '${business.description.replaceAll("'", "''").replaceAll("\"", "\"\"")}'::text, website = '${business.website}'::text, type = '${business.type.name}'::text, "contactName" = '${business.contactName.replaceAll("'", "''").replaceAll("\"", "\"\"")}'::text, "contactPhone" = '${business.contactPhone}'::text, "contactEmail" = '${business.contactEmail}'::text, notes = '${business.notes.replaceAll("'", "''").replaceAll("\"", "\"\"")}'::text, "locationName" = '${business.locationName.replaceAll("'", "''").replaceAll("\"", "\"\"")}'::text, "locationAddress" = '${business.locationAddress.replaceAll("'", "''").replaceAll("\"", "\"\"")}'::text WHERE
id = ${business.id};
'''
);
''');
var logoResponse = await http.get(
Uri.http('logo.clearbit.com', '/${business.website}'),
@ -260,18 +247,17 @@ void main() async {
try {
await File('logos/${business.id}.png').delete();
} catch(e) {
} catch (e) {
print('Failure to delete logo! $e');
}
if (logoResponse.headers.toString().contains('image/png')) {
await File('logos/${business.id}.png').writeAsBytes(logoResponse.bodyBytes);
await File('logos/${business.id}.png')
.writeAsBytes(logoResponse.bodyBytes);
}
return Response.ok(
business.id.toString(),
headers: {'Access-Control-Allow-Origin': '*'},
business.id.toString(),
headers: {'Access-Control-Allow-Origin': '*'},
);
} on JWTExpiredException {
print('JWT Expired');
@ -280,8 +266,8 @@ void main() async {
}
return Response.unauthorized(
'unauthorized',
headers: {'Access-Control-Allow-Origin': '*'},
'unauthorized',
headers: {'Access-Control-Allow-Origin': '*'},
);
});
app.post('/fbla-api/signin', (Request request) async {
@ -292,13 +278,12 @@ void main() async {
var username = json['username'];
var password = json['password'];
var saltDb = await postgres.query(
'SELECT salt FROM users WHERE username=\'$username\''
);
var saltDb = await postgres
.query('SELECT salt FROM users WHERE username=\'$username\'');
if (saltDb.isEmpty) {
return Response.unauthorized(
'invalid username',
headers: {'Access-Control-Allow-Origin': '*'},
'invalid username',
headers: {'Access-Control-Allow-Origin': '*'},
);
}
@ -320,17 +305,13 @@ void main() async {
argon2.generateBytes(passwordBytes, result);
var resultHex = result.toHexString();
var passwordHashDb = await postgres.query(
'SELECT password_hash FROM users WHERE username=\'$username\''
);
var passwordHashDb = await postgres
.query('SELECT password_hash FROM users WHERE username=\'$username\'');
var passwordHash = passwordHashDb[0][0].toString();
if (passwordHash == resultHex) {
final jwt = JWT(
{
'username': username
},
{'username': username},
);
final token = jwt.sign(secretKey);
try {
@ -342,14 +323,13 @@ void main() async {
}
return Response.ok(
token.toString(),
headers: {'Access-Control-Allow-Origin': '*'},
token.toString(),
headers: {'Access-Control-Allow-Origin': '*'},
);
} else {
return Response.unauthorized(
'invalid password',
headers: {'Access-Control-Allow-Origin': '*'},
'invalid password',
headers: {'Access-Control-Allow-Origin': '*'},
);
}
});
@ -367,7 +347,8 @@ void main() async {
var password = json['password'];
var r = Random.secure();
String randomSalt = String.fromCharCodes(List.generate(32, (index) => r.nextInt(33) + 89));
String randomSalt = String.fromCharCodes(
List.generate(32, (index) => r.nextInt(33) + 89));
final salt = randomSalt.toBytesLatin1();
var parameters = Argon2Parameters(
@ -385,27 +366,24 @@ void main() async {
argon2.generateBytes(passwordBytes, result);
var resultHex = result.toHexString();
postgres.query(
'''
postgres.query('''
INSERT INTO public.users (username, password_hash, salt)
VALUES ('$username', '$resultHex', '$randomSalt')
'''
);
''');
return Response.ok(
username,
headers: {'Access-Control-Allow-Origin': '*'},
username,
headers: {'Access-Control-Allow-Origin': '*'},
);
} on JWTExpiredException {
print('JWT Expired');
print('JWT Expired');
} on JWTException catch (e) {
print(e.message);
}
return Response.unauthorized(
'unauthorized',
headers: {'Access-Control-Allow-Origin': '*'},
'unauthorized',
headers: {'Access-Control-Allow-Origin': '*'},
);
});
app.post('/fbla-api/deleteuser', (Request request) async {
@ -420,18 +398,15 @@ void main() async {
var json = jsonDecode(payload);
var username = json['username'];
postgres.query(
'''
postgres.query('''
DELETE FROM public.users
WHERE username IN ('$username');
'''
);
''');
return Response.ok(
username,
headers: {'Access-Control-Allow-Origin': '*'},
username,
headers: {'Access-Control-Allow-Origin': '*'},
);
} on JWTExpiredException {
print('JWT Expired');
} on JWTException catch (e) {
@ -439,8 +414,8 @@ void main() async {
}
return Response.unauthorized(
'unauthorized',
headers: {'Access-Control-Allow-Origin': '*'},
'unauthorized',
headers: {'Access-Control-Allow-Origin': '*'},
);
});
app.get('/fbla-api/marinodev', (Request request) async {
@ -450,11 +425,11 @@ void main() async {
List<int> content = logo.readAsBytesSync();
return Response.ok(
content,
headers: {
'Access-Control-Allow-Origin': '*',
'Content-Type': 'image/svg+xml'
},
content,
headers: {
'Access-Control-Allow-Origin': '*',
'Content-Type': 'image/svg+xml'
},
);
});