30 Commits
Author SHA1 Message Date
drake 9116876f7b API Rewrite 2024-06-13 14:27:36 -05:00
drake 0a1250dfd2 API Listing half-rewrite 2024-06-12 14:28:13 -05:00
drake 68edb2c3a1 fixes 4 2024-06-06 21:55:56 -05:00
drake ee8b419887 fixes 3 2024-06-06 21:40:28 -05:00
drake d350dde994 fixes 2 2024-06-06 21:31:30 -05:00
drake 00a4965efc fixes 2024-06-06 21:17:31 -05:00
drake 013dc5572b test 2 2024-06-06 21:00:43 -05:00
drake 086f47cab0 test 2024-06-06 20:25:15 -05:00
drake dd0b7460fb fix env vars 2024-06-06 20:10:38 -05:00
drake 6bdb53ecd9 test3 2024-06-06 20:08:26 -05:00
drake 8084532ba1 test2 2024-06-06 20:06:43 -05:00
drake 8efffef7c9 test 2024-06-06 20:05:34 -05:00
drake 9ac5b280d0 fix api address & adjust linux build 2024-06-06 19:48:26 -05:00
drake 96b608d0c1 reformat jenkinsfile again x6 2024-06-06 18:49:18 -05:00
drake bf53db3524 reformat jenkinsfile again x5 2024-06-06 18:32:51 -05:00
drake bdc69a5dc0 reformat jenkinsfile again x4 2024-06-06 18:14:12 -05:00
drake a81cb9ab73 reformat jenkinsfile again x3 2024-06-06 18:12:43 -05:00
drake 5fe4201060 reformat jenkinsfile again x2 2024-06-06 18:06:47 -05:00
drake 355a5b2532 reformat jenkinsfile again 2024-06-06 18:03:17 -05:00
drake abf893cef3 reformat jenkinsfile 2024-06-06 18:00:33 -05:00
drake 339f64ac0d reformat jenkinsfile 2024-06-06 16:41:37 -05:00
jenkins d5e7de8f50 security updates part 2 2024-06-06 15:44:28 -05:00
jenkins e1ab786140 security updates 2024-06-06 15:13:53 -05:00
drake 8f8797fbe6 readme fixes 2024-04-30 03:01:27 +00:00
drake e440438a8a after SLC rubric and README.md 2024-04-29 21:58:55 -05:00
drake 9b8dcda882 Update fbla-api/README.md 2024-04-22 14:05:35 +00:00
drake 5e1b1e3a1f Update fbla_ui/README.md 2024-04-17 15:37:23 +00:00
drake 501a8113b2 Update readme formatting and packages 2024-04-16 13:56:13 +00:00
drake 9b30a0c16d Update readme formatting 2024-04-10 14:48:33 +00:00
drake 5a560fbae8 Update Readme for WI SLC 2024-04-10 14:43:46 +00:00
18 changed files with 801 additions and 326 deletions
Vendored
+137
View File
@@ -0,0 +1,137 @@
pipeline {
agent any
stages {
stage('Flutter Cleanup/Update') {
steps {
sh '''cd fbla_ui
flutter upgrade --force
flutter pub upgrade
flutter --version
flutter doctor
flutter clean'''
}
}
stage('Build API & UI') {
parallel {
stage('Build API') {
steps {
sh '''cd fbla-api
docker image prune -f
docker build --no-cache -t fbla-api .'''
}
}
stage('UI Web Build') {
steps {
sh '''cd fbla_ui
flutter build web --release --base-href /fbla/'''
}
}
stage('UI Linux Build') {
steps {
sh '''cd fbla_ui
flutter build linux --release'''
}
}
stage('UI APK Build') {
steps {
sh '''cd fbla_ui
flutter build apk --release'''
}
}
}
}
stage('Deploy and Save') {
parallel {
stage('Save Other Builds') {
steps {
script {
def remote = [
name : 'HostServer',
host : '192.168.0.216',
user : "${env.JOBLINK_LOCAL_USER}",
password : "${env.JOBLINK_LOCAL_PASSWD}",
allowAnyHosts: true,
]
if (env.BRANCH_NAME == 'main') {
sshRemove(path: "/home/${env.JOBLINK_LOCAL_USER}/builds/main/linux", remote: remote)
sshCommand remote: remote, command: "mkdir /home/${env.JOBLINK_LOCAL_USER}/builds/main/linux"
sshPut(from: 'fbla_ui/build/linux/x64/release', into: "/home/${env.JOBLINK_LOCAL_USER}/builds/main/linux", remote: remote)
sshCommand remote: remote, command: "mv /home/${env.JOBLINK_LOCAL_USER}/builds/main/linux/release/* /home/${env.JOBLINK_LOCAL_USER}/builds/main/linux"
sshCommand remote: remote, command: "rm -R /home/${env.JOBLINK_LOCAL_USER}/builds/main/linux/release/"
sshRemove(path: "/home/${env.JOBLINK_LOCAL_USER}/builds/main/apk", remote: remote)
sshCommand remote: remote, command: "mkdir /home/${env.JOBLINK_LOCAL_USER}/builds/main/apk"
sshPut(from: 'fbla_ui/build/app/outputs/apk/release', into: "/home/${env.JOBLINK_LOCAL_USER}/builds/main/apk", remote: remote)
sshCommand remote: remote, command: "mv /home/${env.JOBLINK_LOCAL_USER}/builds/main/apk/release/* /home/${env.JOBLINK_LOCAL_USER}/builds/main/apk"
sshCommand remote: remote, command: "rm -R /home/${env.JOBLINK_LOCAL_USER}/builds/main/apk/release/"
} else {
sshRemove(path: "/home/${env.JOBLINK_LOCAL_USER}/builds/dev/linux", remote: remote)
sshCommand remote: remote, command: "mkdir /home/${env.JOBLINK_LOCAL_USER}/builds/dev/linux"
sshPut(from: 'fbla_ui/build/linux/x64/release', into: "/home/${env.JOBLINK_LOCAL_USER}/builds/dev/linux", remote: remote)
sshCommand remote: remote, command: "mv /home/${env.JOBLINK_LOCAL_USER}/builds/dev/linux/release/* /home/${env.JOBLINK_LOCAL_USER}/builds/dev/linux"
sshCommand remote: remote, command: "rm -R /home/${env.JOBLINK_LOCAL_USER}/builds/dev/linux/release/"
sshRemove(path: "/home/${env.JOBLINK_LOCAL_USER}/builds/dev/apk", remote: remote)
sshCommand remote: remote, command: "mkdir /home/${env.JOBLINK_LOCAL_USER}/builds/dev/apk"
sshPut(from: 'fbla_ui/build/app/outputs/apk/release', into: "/home/${env.JOBLINK_LOCAL_USER}/builds/dev/apk", remote: remote)
sshCommand remote: remote, command: "mv /home/${env.JOBLINK_LOCAL_USER}/builds/dev/apk/release/* /home/${env.JOBLINK_LOCAL_USER}/builds/dev/apk"
sshCommand remote: remote, command: "rm -R /home/${env.JOBLINK_LOCAL_USER}/builds/dev/apk/release/"
}
}
}
}
stage('Deploy Remote Web UI') {
when {
expression {
env.BRANCH_NAME == 'main'
}
}
steps {
script {
def remote = [
name : 'MarinoDev',
host : 'marinodev.com',
port : 21098,
user : "${env.JOBLINK_REMOTE_USER}",
identityFile : '/var/jenkins_home/marinoDevPrivateKey',
passphrase : "${env.JOBLINK_REMOTE_PASSWD}",
allowAnyHosts: true,
]
sshRemove(path: "/home/${env.JOBLINK_REMOTE_USER}/public_html/fbla", remote: remote)
sshPut(from: 'fbla_ui/build/web/', into: "/home/${env.JOBLINK_REMOTE_USER}/public_html/", remote: remote)
sshCommand remote: remote, command: "mv /home/${env.JOBLINK_REMOTE_USER}/public_html/web /home/${env.JOBLINK_REMOTE_USER}/public_html/fbla"
}
}
}
stage('Deploy Local Web UI') {
steps {
script {
def remote = [
name : 'HostServer',
host : '192.168.0.216',
user : "${env.JOBLINK_LOCAL_USER}",
password : "${env.JOBLINK_LOCAL_PASSWD}",
allowAnyHosts: true,
]
sshRemove(path: "/home/${env.JOBLINK_LOCAL_USER}/fbla-webserver/webfiles/fbla", remote: remote)
sshPut(from: 'fbla_ui/build/web/', into: "/home/${env.JOBLINK_LOCAL_USER}/fbla-webserver", remote: remote)
sshCommand remote: remote, command: "mv /home/${env.JOBLINK_LOCAL_USER}/fbla-webserver/web /home/${env.JOBLINK_LOCAL_USER}/fbla-webserver/webfiles/fbla"
}
}
}
stage('Start API') {
steps {
sh '''cd fbla-api
docker-compose down
docker-compose up -d'''
}
}
}
}
stage('Run API Tests') {
steps {
sh '''cd fbla-api
dart pub get
dart run ./test/fbla_api_test.dart'''
}
}
}
}
+54 -3
View File
@@ -1,5 +1,56 @@
This is my app `Job Link` for the 2023-2024 FBLA Coding and Programming event.
It uses the [Flutter Framework](https://flutter.dev/) for the front end and [Dart Language](https://dart.dev/) for both the front end and API. # Job Link
Please view the README in [fbla_ui](fbla_ui/README.md) and [fbla-api](fbla-api/README.md) for specific instructions for installation and usage for each part of the app This is my app `Job Link` for the 2023-2024 FBLA Coding and Programming event.\
WI SLC Winner.
It uses the [Flutter Framework](https://flutter.dev/) for the front end and the [Dart Language](https://dart.dev/) for both the front end and API.
## 3rd Party Libraries
- [dart_jsonwebtoken](https://pub.dev/packages/dart_jsonwebtoken)
- [sliver_tools](https://pub.dev/packages/sliver_tools)
- [flutter_sticky_header](https://pub.dev/packages/flutter_sticky_header)
- [pdf](https://pub.dev/packages/pdf)
- [printing](https://pub.dev/packages/printing)
- [open_filex](https://pub.dev/packages/open_filex)
- [postgres](https://pub.dev/packages/postgres)
- [argon2](https://pub.dev/packages/argon2)
## Requirements
### Job Link
- **OS**: Windows, Linux, MacOS, Android, IOS. Note that some releases may not contain a MacOS or IOS build.
- Stable internet connection.
### API
- **OS**: Windows, Linux, MacOS.
- Stable internet connection.
## Installation/Usage
Please view the README in [fbla_ui](fbla_ui/README.md) and [fbla-api](fbla-api/README.md) for specific instructions for installation and usage for each part of the app.
## Competitions
[Here](https://docs.google.com/presentation/d/1ZbSE9RqobU2T-NDIm3CUtT_9nEhOm3_B47NZl1-c_QA) is the presentation used for competitions.
### WI State Leadership Conference
1st Place\
Used release 0.1.1\
[Here](SLC) are my score sheets.
Questions asked (with my answers):
**Q**: Why did you decide to use the apps (framework and tools I assume) you used?\
**A**: I decided to use Flutter primarily because of its cross-platform capabilities and its integration with the [Material design specification](https://m3.material.io/). I also decided to use it because I had some previous experience with Flutter and Dart, and Dart is somewhat similar to Java which I also had experience with.
This one seems to just be a clarification for the `User input is validated` category of the [scoring sheet](https://connect.fbla.org/headquarters/files/High%20School%20Competitive%20Events%20Resources/Individual%20Guidelines/Presentation%20Events/Coding--Programming.pdf) (page 5-6)\
**Q**: You mentioned that you validated that the description [of the business] is required, do you validate all the inputs or just that?\
**A**: I validate that all of the required fields are inputted, and I also check for a valid email address and website format.
This seems to be for the [scoring sheet](https://connect.fbla.org/headquarters/files/High%20School%20Competitive%20Events%20Resources/Individual%20Guidelines/Presentation%20Events/Coding--Programming.pdf) (page 5-6) `Code Quality` section.\
While looking through a binder of the presentation and source code:\
**Q**: Is your source code all properly commented?\
**A**: While it is hard to comment UI code because of the nature of it, I did my best to use comments where applicable, and I also provide extensive documentation of the installation and usage of the app in the documentation in the README files.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -9,7 +9,7 @@ RUN echo 'deb [signed-by=/usr/share/keyrings/dart.gpg arch=amd64] https://storag
RUN apt-get update && apt-get install -y dart RUN apt-get update && apt-get install -y dart
ENV PATH="$PATH:/usr/lib/dart/bin" ENV PATH="$PATH:/usr/lib/dart/bin"
RUN cd /root && git clone https://https://git.marinodev.com/MarinoDev/FBLA24.git RUN cd /root && git clone https://git.marinodev.com/MarinoDev/FBLA24.git
WORKDIR /root/FBLA24/fbla-api WORKDIR /root/FBLA24/fbla-api
RUN dart pub install RUN dart pub install
-1
View File
@@ -16,6 +16,5 @@ docker-compose up -d'''
dart run ./test/fbla_api_test.dart''' dart run ./test/fbla_api_test.dart'''
} }
} }
} }
} }
+30 -20
View File
@@ -2,19 +2,16 @@ This is the API for my 2023-2024 FBLA Coding & Programming App
## Installation ## Installation
1. Install [Dart SDK](https://dart.dev/get-dart) 1. Install [Dart SDK](https://dart.dev/get-dart).
2. Install [PostgreSQL](https://www.postgresql.org/) and set it up 2. Clone the repo .
3. Clone the repo ```bash
```
git clone https://git.marinodev.com/MarinoDev/FBLA24.git git clone https://git.marinodev.com/MarinoDev/FBLA24.git
cd FBLA24/fbla-api/ cd FBLA24/fbla-api/
``` ```
4. Run `dart pub install` to install dart packages 3. Run `dart pub install` to install dart packages.
4. Install [PostgreSQL](https://www.postgresql.org/) and set it up.
## Usage 5. Create `fbla` database in postgres.
```SQL
1. Create `fbla` database in postgres
```
CREATE DATABASE fbla CREATE DATABASE fbla
WITH WITH
OWNER = [username] OWNER = [username]
@@ -24,8 +21,8 @@ CREATE DATABASE fbla
``` ```
Make sure to change [username] to the actual username of your postgres instance. Make sure to change [username] to the actual username of your postgres instance.
2. Create `businesses` table 6. Create `businesses` table.
``` ```SQL
-- Table: public.businesses -- Table: public.businesses
-- DROP TABLE IF EXISTS public.businesses; -- DROP TABLE IF EXISTS public.businesses;
@@ -51,10 +48,10 @@ TABLESPACE pg_default;
ALTER TABLE IF EXISTS public.businesses ALTER TABLE IF EXISTS public.businesses
OWNER to [username]; OWNER to [username];
``` ```
Make sure to change [username] to the actual username of your postgres instance Make sure to change [username] to the actual username of your postgres instance.
3. Create `users` table 7. Create `users` table.
``` ```SQL
-- Table: public.users -- Table: public.users
-- DROP TABLE IF EXISTS public.users; -- DROP TABLE IF EXISTS public.users;
@@ -73,9 +70,22 @@ TABLESPACE pg_default;
ALTER TABLE IF EXISTS public.users ALTER TABLE IF EXISTS public.users
OWNER to postgres; OWNER to postgres;
``` ```
4. Set environment variables `POSTGRES_ADDRESS` (IP address), `POSTGRES_PORT` (default 5432), `POSTGRES_USERNAME`, and `POSTGRES_PASSWORD` to appropriate information for your postgres database. Also set `SECRET_KEY` to anything you want to genera te JSON Web Tokens. 8. Set environment variables `JOBLINK_POSTGRES_ADDRESS` (IP address), `JOBLINK_POSTGRES_PORT` (default 5432), `JOBLINK_POSTGRES_USERNAME`, and `JOBLINK_POSTGRES_PASSWORD` to appropriate information for your postgres database. Also set `JOBLINK_SECRET_KEY` to anything you want to generate JSON Web Tokens.
5. Set lib/create_first_user.dart username and password variables at top of file and run with `dart run lib/create_first_user.dart` 9. Set lib/create_first_user.dart username and password variables at top of file and run with `dart run lib/create_first_user.dart`.\
Note: the username and password you use here will be what you use to log into the app as an admin Note: the username and password you use here will be what you use to log into the app as an admin.
6. Your database should be all set up! Start the API with `dart run lib/fbla_api.dart` or alternatively, run it in a docker container with [Docker Build](https://docs.docker.com/reference/cli/docker/image/build/) and [Docker Compose](https://docs.docker.com/compose/) using the included [Dockerfile](Dockerfile) and [docker-compose.yml](docker-compose.yml) files. If using `Docker Compose`, change the first portion of the volumes path on line 9 to any desired storage location.
## Usage
### Installed
Start the API with `dart run lib/fbla_api.dart`\
Note the address it is serving at, you will need this to connect it to the UI, and to run tests. Note the address it is serving at, you will need this to connect it to the UI, and to run tests.
7. Test your api with `dart run test/fbla_api_test.dart`, setting `apiAddress` on line 8 to your api address.
### Docker
Run it in a docker container with [Docker Build](https://docs.docker.com/reference/cli/docker/image/build/) and [Docker Compose](https://docs.docker.com/compose/) using the included [Dockerfile](Dockerfile) and [docker-compose.yml](docker-compose.yml) files. If using `Docker Compose`, change the first portion of the volumes path on line 9 to any desired storage location.\
Note the address it is serving at, you will need this to connect it to the UI, and to run tests.
### Testing
You can test all functionality of your api with `dart run test/fbla_api_test.dart`, setting `apiAddress` on line 8 to your api address.
+6 -5
View File
@@ -3,13 +3,14 @@ version: '3'
services: services:
fbla_api: fbla_api:
image: fbla-api image: fbla-api
restart: unless-stopped
ports: ports:
- "8000:8000" - "8000:8000"
volumes: volumes:
- /var/jenkins_home/logos:/root/FBLA24/fbla-api/logos - /var/jenkins_home/logos:/root/FBLA24/fbla-api/logos
environment: environment:
- POSTGRES_USERNAME - JOBLINK_POSTGRES_USERNAME
- POSTGRES_PASSWORD - JOBLINK_POSTGRES_PASSWORD
- SECRET_KEY - JOBLINK_SECRET_KEY
- POSTGRES_ADDRESS - JOBLINK_POSTGRES_ADDRESS
- POSTGRES_PORT - JOBLINK_POSTGRES_PORT
+4 -4
View File
@@ -20,11 +20,11 @@ var parameters = Argon2Parameters(
); );
final postgres = PostgreSQLConnection( final postgres = PostgreSQLConnection(
Platform.environment['POSTGRES_ADDRESS']!, Platform.environment['JOBLINK_POSTGRES_ADDRESS']!,
int.parse(Platform.environment['POSTGRES_PORT']!), int.parse(Platform.environment['JOBLINK_POSTGRES_PORT']!),
'fbla', 'fbla',
username: Platform.environment['POSTGRES_USERNAME'], username: Platform.environment['JOBLINK_POSTGRES_USERNAME'],
password: Platform.environment['POSTGRES_PASSWORD'], password: Platform.environment['JOBLINK_POSTGRES_PASSWORD'],
); );
Future<void> main() async { Future<void> main() async {
+269 -96
View File
@@ -2,16 +2,16 @@ import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'dart:math'; import 'dart:math';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:argon2/argon2.dart';
import 'package:dart_jsonwebtoken/dart_jsonwebtoken.dart'; import 'package:dart_jsonwebtoken/dart_jsonwebtoken.dart';
import 'package:http/http.dart' as http;
import 'package:postgres/postgres.dart'; import 'package:postgres/postgres.dart';
import 'package:shelf/shelf.dart'; import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart' as io; import 'package:shelf/shelf_io.dart' as io;
import 'package:shelf_router/shelf_router.dart'; 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']!);
SecretKey secretKey = SecretKey(Platform.environment['SECRET_KEY']!);
enum BusinessType { enum BusinessType {
food, food,
@@ -22,47 +22,37 @@ enum BusinessType {
other, other,
} }
enum JobType { cashier, server, mechanic, other }
class Business { class Business {
int id; int id;
String name; String name;
String description; String description;
BusinessType type; String? website;
String website; String? contactName;
String contactName; String? contactEmail;
String contactEmail; String? contactPhone;
String contactPhone; String? notes;
String notes; String? locationName;
String locationName; String? locationAddress;
String locationAddress;
Business({ Business(
required this.id, {required this.id,
required this.name, required this.name,
required this.description, required this.description,
required this.type, this.website,
required this.website, this.contactName,
required this.contactName, this.contactEmail,
required this.contactEmail, this.contactPhone,
required this.contactPhone, this.notes,
required this.notes, this.locationName,
required this.locationName, this.locationAddress});
required this.locationAddress,
});
factory Business.fromJson(Map<String, dynamic> json) { factory Business.fromJson(Map<String, dynamic> json) {
bool typeValid = true;
try {
BusinessType.values.byName(json['type']);
} catch (e) {
typeValid = false;
}
return Business( return Business(
id: json['id'], id: json['id'],
name: json['name'], name: json['name'],
description: json['description'], description: json['description'],
type: typeValid
? BusinessType.values.byName(json['type'])
: BusinessType.other,
website: json['website'], website: json['website'],
contactName: json['contactName'], contactName: json['contactName'],
contactEmail: json['contactEmail'], contactEmail: json['contactEmail'],
@@ -74,9 +64,46 @@ class Business {
} }
} }
class JobListing {
String? id;
String? businessId;
String name;
String description;
JobType type;
String? wage;
String? link;
JobListing(
{this.id,
this.businessId,
required this.name,
required this.description,
required this.type,
this.wage,
this.link});
factory JobListing.fromJson(Map<String, dynamic> json) {
bool typeValid = true;
try {
JobType.values.byName(json['type']);
} catch (e) {
typeValid = false;
}
return JobListing(
id: json['id'],
businessId: json['businessId'],
name: json['name'],
description: json['description'],
type: typeValid ? JobType.values.byName(json['type']) : JobType.other,
wage: json['wage'],
link: json['link'],
);
}
}
Future<String> fetchBusinessData() async { Future<String> fetchBusinessData() async {
final result = await postgres.query( final result = await postgres.query('''
'''
SELECT json_agg( SELECT json_agg(
json_build_object( json_build_object(
'id', id, 'id', id,
@@ -92,12 +119,9 @@ Future<String> fetchBusinessData() async {
'locationAddress', "locationAddress" 'locationAddress', "locationAddress"
) )
) FROM businesses ) FROM businesses
''' ''');
);
var encoded = json.encode(result); var encoded = json.encode(result[0][0]);
var decoded = json.decode(encoded);
encoded = json.encode(decoded[0][0]);
return encoded; return encoded;
} }
@@ -105,17 +129,14 @@ Future<String> fetchBusinessData() async {
String _hostname = 'localhost'; String _hostname = 'localhost';
const _port = 8000; const _port = 8000;
final postgres = PostgreSQLConnection( final postgres = PostgreSQLConnection(
Platform.environment['POSTGRES_ADDRESS']!, Platform.environment['JOBLINK_POSTGRES_ADDRESS']!,
int.parse(Platform.environment['POSTGRES_PORT']!), int.parse(Platform.environment['JOBLINK_POSTGRES_PORT']!),
'fbla', 'fbla',
username: Platform.environment['POSTGRES_USERNAME'], username: Platform.environment['JOBLINK_POSTGRES_USERNAME'],
password: Platform.environment['POSTGRES_PASSWORD'], password: Platform.environment['JOBLINK_POSTGRES_PASSWORD'],
); );
void main() async { void main() async {
await postgres.open(); await postgres.open();
@@ -130,12 +151,95 @@ void main() async {
headers: {'Access-Control-Allow-Origin': '*'}, headers: {'Access-Control-Allow-Origin': '*'},
); );
}); });
app.get('/fbla-api/businessdata/overview', (Request request) async {
print('business overview request received');
var filters = request.url.queryParameters['filters']?.split(',') ??
JobType.values.asNameMap().keys;
// List<Map<String, List<Map<String, dynamic>>>> this is the real type lol
List<dynamic> output = [];
for (int i = 0; i < filters.length; i++) {
var postgresResult = (await postgres.query('''
SELECT json_agg(
json_build_object(
'id', id,
'name', name,
'description', description,
'website', website,
'contactEmail', "contactEmail",
'contactPhone', "contactPhone",
'locationName', "locationName"
)
) FROM public.businesses WHERE id IN (SELECT "businessId" FROM public.listings WHERE type='${filters.elementAt(i)}')
'''))[0][0];
if (postgresResult != null) {
output.add({filters.elementAt(i): postgresResult});
}
}
return Response.ok(
json.encode(output),
headers: {
'Access-Control-Allow-Origin': '*',
'Content-Type': 'text/plain'
},
);
});
app.get('/fbla-api/businessdata/business/<business>',
(Request request, String business) async {
print('idividual business data request received');
var result = (await postgres.query('''
SELECT
json_build_object(
'id', b.id,
'name', b.name,
'description', b.description,
'website', b.website,
'contactName', b."contactName",
'contactEmail', b."contactEmail",
'contactPhone', b."contactPhone",
'notes', b.notes,
'locationName', b."locationName",
'locationAddress', b."locationAddress",
'listings',
json_agg(
json_build_object(
'id', l.id,
'name', l.name,
'description', l.description,
'type', l.type,
'wage', l.wage,
'link', l.link
)
)
)
FROM businesses b
LEFT JOIN listings l ON b.id = l.business_id
WHERE b.id = $business
GROUP BY b.id;
'''))[0][0];
return Response.ok(
json.encode(result),
headers: {
'Access-Control-Allow-Origin': '*',
'Content-Type': 'text/plain'
},
);
});
app.get('/fbla-api/businessdata', (Request request) async { app.get('/fbla-api/businessdata', (Request request) async {
print('business data request received'); print('business data request received');
final output = await fetchBusinessData(); final output = await fetchBusinessData();
return Response.ok( return Response.ok(
output.toString(), output.toString(),
headers: {'Access-Control-Allow-Origin': '*'}, headers: {
'Access-Control-Allow-Origin': '*',
'Content-Type': 'text/plain'
},
); );
}); });
app.get('/fbla-api/logos/<logo>', (Request request, String logoId) { app.get('/fbla-api/logos/<logo>', (Request request, String logoId) {
@@ -162,15 +266,12 @@ void main() async {
var json = jsonDecode(payload); var json = jsonDecode(payload);
Business business = Business.fromJson(json); Business business = Business.fromJson(json);
await postgres.query( await postgres.query('''
''' INSERT INTO businesses (name, description, website, "contactName", "contactPhone", "contactEmail", notes, "locationName", "locationAddress")
INSERT INTO businesses (name, description, type, website, "contactName", "contactPhone", "contactEmail", notes, "locationName", "locationAddress") VALUES ('${business.name.replaceAll("'", "''")}', '${business.description.replaceAll("'", "''")}', '${business.website ?? 'NULL'}', '${business.contactName?.replaceAll("'", "''") ?? 'NULL'}', '${business.contactPhone ?? 'NULL'}', '${business.contactEmail ?? 'NULL'}', '${business.notes?.replaceAll("'", "''") ?? 'NULL'}', '${business.locationName?.replaceAll("'", "''") ?? 'NULL'}', '${business.locationAddress?.replaceAll("'", "''") ?? 'NULL'}')
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( final dbBusiness = await postgres.query('''SELECT * FROM public.businesses
'''SELECT * FROM public.businesses
ORDER BY id DESC LIMIT 1'''); ORDER BY id DESC LIMIT 1''');
var id = dbBusiness[0][0]; var id = dbBusiness[0][0];
var logoResponse = await http.get( var logoResponse = await http.get(
@@ -195,10 +296,43 @@ void main() async {
headers: {'Access-Control-Allow-Origin': '*'}, headers: {'Access-Control-Allow-Origin': '*'},
); );
}); });
app.post('/fbla-api/createlisting', (Request request) async {
print('create business request received');
final payload = await request.readAsString();
var auth = request.headers['Authorization']?.replaceAll('Bearer ', '');
try {
JWT.verify(auth!, secretKey);
var json = jsonDecode(payload);
JobListing listing = JobListing.fromJson(json);
await postgres.query('''
INSERT INTO listings ("businessId", name, description, type, wage, link)
VALUES ('${listing.businessId}' '${listing.name.replaceAll("'", "''")}', '${listing.description.replaceAll("'", "''")}', '${listing.type.name}', '${listing.wage ?? 'NULL'}', '${listing.link?.replaceAll("'", "''") ?? 'NULL'}')
''');
final dbListing = await postgres.query('''SELECT id FROM public.listings
ORDER BY id DESC LIMIT 1''');
var id = dbListing[0][0];
return Response.ok(
id.toString(),
headers: {'Access-Control-Allow-Origin': '*'},
);
} on JWTExpiredException {
print('JWT Expired');
} on JWTException catch (e) {
print(e.message);
}
return Response.unauthorized(
'unauthorized',
headers: {'Access-Control-Allow-Origin': '*'},
);
});
app.post('/fbla-api/deletebusiness', (Request request) async { app.post('/fbla-api/deletebusiness', (Request request) async {
print('delete business request received'); print('delete business request received');
final payload = await request.readAsString(); final payload = await request.readAsString();
var auth = request.headers['Authorization']?.replaceAll('Bearer ', ''); var auth = request.headers['Authorization']?.replaceAll('Bearer ', '');
try { try {
@@ -206,17 +340,11 @@ void main() async {
var json = jsonDecode(payload); var json = jsonDecode(payload);
var id = json['id']; var id = json['id'];
await postgres.query( await postgres.query('DELETE FROM public.business WHERE id=$id;');
'''
DELETE FROM public.businesses
WHERE id IN
($id);
'''
);
try{ try {
await File('logos/$id.png').delete(); await File('logos/$id.png').delete();
} catch(e) { } catch (e) {
print('Failure to delete logo! $e'); print('Failure to delete logo! $e');
} }
@@ -235,6 +363,33 @@ void main() async {
headers: {'Access-Control-Allow-Origin': '*'}, headers: {'Access-Control-Allow-Origin': '*'},
); );
}); });
app.post('/fbla-api/deletelisting', (Request request) async {
print('delete listing request received');
final payload = await request.readAsString();
var auth = request.headers['Authorization']?.replaceAll('Bearer ', '');
try {
JWT.verify(auth!, secretKey);
var json = jsonDecode(payload);
var id = json['id'];
await postgres.query('DELETE FROM public.listings WHERE id=$id;');
return Response.ok(
id.toString(),
headers: {'Access-Control-Allow-Origin': '*'},
);
} on JWTExpiredException {
print('JWT Expired');
} on JWTException catch (e) {
print(e.message);
}
return Response.unauthorized(
'unauthorized',
headers: {'Access-Control-Allow-Origin': '*'},
);
});
app.post('/fbla-api/editbusiness', (Request request) async { app.post('/fbla-api/editbusiness', (Request request) async {
print('edit business request received'); print('edit business request received');
@@ -246,13 +401,11 @@ void main() async {
var json = jsonDecode(payload); var json = jsonDecode(payload);
Business business = Business.fromJson(json); Business business = Business.fromJson(json);
await postgres.query( await postgres.query('''
'''
UPDATE businesses SET 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 name = '${business.name.replaceAll("'", "''").replaceAll("\"", "\"\"")}'::text, description = '${business.description.replaceAll("'", "''").replaceAll("\"", "\"\"")}'::text, website = '${business.website!}'::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}; id = ${business.id};
''' ''');
);
var logoResponse = await http.get( var logoResponse = await http.get(
Uri.http('logo.clearbit.com', '/${business.website}'), Uri.http('logo.clearbit.com', '/${business.website}'),
@@ -260,15 +413,14 @@ void main() async {
try { try {
await File('logos/${business.id}.png').delete(); await File('logos/${business.id}.png').delete();
} catch(e) { } catch (e) {
print('Failure to delete logo! $e'); print('Failure to delete logo! $e');
} }
if (logoResponse.headers.toString().contains('image/png')) { 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( return Response.ok(
business.id.toString(), business.id.toString(),
headers: {'Access-Control-Allow-Origin': '*'}, headers: {'Access-Control-Allow-Origin': '*'},
@@ -284,6 +436,38 @@ void main() async {
headers: {'Access-Control-Allow-Origin': '*'}, headers: {'Access-Control-Allow-Origin': '*'},
); );
}); });
app.post('/fbla-api/editlisting', (Request request) async {
print('edit listing request received');
final payload = await request.readAsString();
var auth = request.headers['Authorization']?.replaceAll('Bearer ', '');
try {
JWT.verify(auth!, secretKey);
var json = jsonDecode(payload);
JobListing listing = JobListing.fromJson(json);
await postgres.query('''
UPDATE listings SET
"businessId" = ${listing.businessId}, name = '${listing.name.replaceAll("'", "''")}'::text, description = '${listing.description.replaceAll("'", "''")}'::text, type = '${listing.type.name}'::text, wage = '${listing.wage ?? 'NULL'}'::text, link = '${listing.link?.replaceAll("'", "''") ?? 'NULL'}'::text WHERE
id = ${listing.id};
''');
return Response.ok(
listing.id.toString(),
headers: {'Access-Control-Allow-Origin': '*'},
);
} on JWTExpiredException {
print('JWT Expired');
} on JWTException catch (e) {
print(e.message);
}
return Response.unauthorized(
'unauthorized',
headers: {'Access-Control-Allow-Origin': '*'},
);
});
app.post('/fbla-api/signin', (Request request) async { app.post('/fbla-api/signin', (Request request) async {
print('signin request received'); print('signin request received');
@@ -292,9 +476,8 @@ void main() async {
var username = json['username']; var username = json['username'];
var password = json['password']; var password = json['password'];
var saltDb = await postgres.query( var saltDb = await postgres
'SELECT salt FROM users WHERE username=\'$username\'' .query('SELECT salt FROM users WHERE username=\'$username\'');
);
if (saltDb.isEmpty) { if (saltDb.isEmpty) {
return Response.unauthorized( return Response.unauthorized(
'invalid username', 'invalid username',
@@ -320,17 +503,13 @@ void main() async {
argon2.generateBytes(passwordBytes, result); argon2.generateBytes(passwordBytes, result);
var resultHex = result.toHexString(); var resultHex = result.toHexString();
var passwordHashDb = await postgres.query( var passwordHashDb = await postgres
'SELECT password_hash FROM users WHERE username=\'$username\'' .query('SELECT password_hash FROM users WHERE username=\'$username\'');
);
var passwordHash = passwordHashDb[0][0].toString(); var passwordHash = passwordHashDb[0][0].toString();
if (passwordHash == resultHex) { if (passwordHash == resultHex) {
final jwt = JWT( final jwt = JWT(
{ {'username': username},
'username': username
},
); );
final token = jwt.sign(secretKey); final token = jwt.sign(secretKey);
try { try {
@@ -345,7 +524,6 @@ void main() async {
token.toString(), token.toString(),
headers: {'Access-Control-Allow-Origin': '*'}, headers: {'Access-Control-Allow-Origin': '*'},
); );
} else { } else {
return Response.unauthorized( return Response.unauthorized(
'invalid password', 'invalid password',
@@ -367,7 +545,8 @@ void main() async {
var password = json['password']; var password = json['password'];
var r = Random.secure(); 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(); final salt = randomSalt.toBytesLatin1();
var parameters = Argon2Parameters( var parameters = Argon2Parameters(
@@ -385,18 +564,15 @@ void main() async {
argon2.generateBytes(passwordBytes, result); argon2.generateBytes(passwordBytes, result);
var resultHex = result.toHexString(); var resultHex = result.toHexString();
postgres.query( postgres.query('''
'''
INSERT INTO public.users (username, password_hash, salt) INSERT INTO public.users (username, password_hash, salt)
VALUES ('$username', '$resultHex', '$randomSalt') VALUES ('$username', '$resultHex', '$randomSalt')
''' ''');
);
return Response.ok( return Response.ok(
username, username,
headers: {'Access-Control-Allow-Origin': '*'}, headers: {'Access-Control-Allow-Origin': '*'},
); );
} on JWTExpiredException { } on JWTExpiredException {
print('JWT Expired'); print('JWT Expired');
} on JWTException catch (e) { } on JWTException catch (e) {
@@ -420,18 +596,15 @@ void main() async {
var json = jsonDecode(payload); var json = jsonDecode(payload);
var username = json['username']; var username = json['username'];
postgres.query( postgres.query('''
'''
DELETE FROM public.users DELETE FROM public.users
WHERE username IN ('$username'); WHERE username IN ('$username');
''' ''');
);
return Response.ok( return Response.ok(
username, username,
headers: {'Access-Control-Allow-Origin': '*'}, headers: {'Access-Control-Allow-Origin': '*'},
); );
} on JWTExpiredException { } on JWTExpiredException {
print('JWT Expired'); print('JWT Expired');
} on JWTException catch (e) { } on JWTException catch (e) {
+82 -45
View File
@@ -5,10 +5,15 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: _fe_analyzer_shared name: _fe_analyzer_shared
sha256: eb376e9acf6938204f90eb3b1f00b578640d3188b4c8a8ec054f9f479af8d051 sha256: "5aaf60d96c4cd00fe7f21594b5ad6a1b699c80a27420f8a837f4d68473ef09e3"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "64.0.0" version: "68.0.0"
_macros:
dependency: transitive
description: dart
source: sdk
version: "0.1.0"
adaptive_number: adaptive_number:
dependency: transitive dependency: transitive
description: description:
@@ -21,10 +26,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: analyzer name: analyzer
sha256: "69f54f967773f6c26c7dcb13e93d7ccee8b17a641689da39e878d5cf13b06893" sha256: "21f1d3720fd1c70316399d5e2bccaebb415c434592d778cce8acb967b8578808"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.2.0" version: "6.5.0"
argon2: argon2:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -37,10 +42,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: args name: args
sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.2" version: "2.5.0"
async: async:
dependency: transitive dependency: transitive
description: description:
@@ -61,10 +66,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: buffer name: buffer
sha256: "8962c12174f53e2e848a6acd7ac7fd63d8a1a6a316c20c458a832d87eba5422a" sha256: "389da2ec2c16283c8787e0adaede82b1842102f8c8aae2f49003a766c5c6b3d1"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.2.0" version: "1.2.3"
charcode: charcode:
dependency: transitive dependency: transitive
description: description:
@@ -73,6 +78,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.1" version: "1.3.1"
clock:
dependency: transitive
description:
name: clock
sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
url: "https://pub.dev"
source: hosted
version: "1.1.1"
collection: collection:
dependency: transitive dependency: transitive
description: description:
@@ -93,10 +106,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: coverage name: coverage
sha256: "2fb815080e44a09b85e0f2ca8a820b15053982b2e714b59267719e8a9ff17097" sha256: "3945034e86ea203af7a056d98e98e42a5518fff200d6e8e6647e1886b07e936e"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.6.3" version: "1.8.0"
crypto: crypto:
dependency: transitive dependency: transitive
description: description:
@@ -109,10 +122,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: dart_jsonwebtoken name: dart_jsonwebtoken
sha256: "6703695f581fc54d0a7e5f281c5538735167605bb9e5abd208c8b330625a92b1" sha256: "346e9a21e4bf6e6a431e19ece00ebb2e3668e1e339cabdf6f46d18d88692a848"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.12.1" version: "2.14.0"
ed25519_edwards: ed25519_edwards:
dependency: transitive dependency: transitive
description: description:
@@ -141,10 +154,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: frontend_server_client name: frontend_server_client
sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.2.0" version: "4.0.0"
glob: glob:
dependency: transitive dependency: transitive
description: description:
@@ -165,10 +178,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: http name: http
sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.1.0" version: "1.2.1"
http_methods: http_methods:
dependency: transitive dependency: transitive
description: description:
@@ -205,10 +218,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: js name: js
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.6.7" version: "0.7.1"
lints: lints:
dependency: "direct dev" dependency: "direct dev"
description: description:
@@ -225,30 +238,38 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.2.0" version: "1.2.0"
macros:
dependency: transitive
description:
name: macros
sha256: "12e8a9842b5a7390de7a781ec63d793527582398d16ea26c60fed58833c9ae79"
url: "https://pub.dev"
source: hosted
version: "0.1.0-main.0"
matcher: matcher:
dependency: transitive dependency: transitive
description: description:
name: matcher name: matcher
sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.12.16" version: "0.12.16+1"
meta: meta:
dependency: transitive dependency: transitive
description: description:
name: meta name: meta
sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.9.1" version: "1.15.0"
mime: mime:
dependency: transitive dependency: transitive
description: description:
name: mime name: mime
sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.4" version: "1.0.5"
node_preamble: node_preamble:
dependency: transitive dependency: transitive
description: description:
@@ -269,10 +290,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: path name: path
sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.8.3" version: "1.9.0"
pedantic: pedantic:
dependency: transitive dependency: transitive
description: description:
@@ -285,10 +306,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: pointycastle name: pointycastle
sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c" sha256: "4be0097fcf3fd3e8449e53730c631200ebc7b88016acecab2b0da2f0149222fe"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.7.3" version: "3.9.1"
pool: pool:
dependency: transitive dependency: transitive
description: description:
@@ -301,10 +322,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: postgres name: postgres
sha256: "98457afc06dd3f9d6892c178ea03ca9659e454107c9be90111e607691998d70d" sha256: f8e4f14734d096277f77ed5dddefcbc1ce18f8f7db5b7ff4b5dd6df2d9db2730
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.6.2" version: "2.6.4"
pub_semver: pub_semver:
dependency: transitive dependency: transitive
description: description:
@@ -365,10 +386,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: shelf_web_socket name: shelf_web_socket
sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1" sha256: "073c147238594ecd0d193f3456a5fe91c4b0abbcc68bf5cd95b36c4e194ac611"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.4" version: "2.0.0"
source_map_stack_trace: source_map_stack_trace:
dependency: transitive dependency: transitive
description: description:
@@ -429,26 +450,26 @@ packages:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: test name: test
sha256: "9b0dd8e36af4a5b1569029949d50a52cb2a2a2fdaa20cebb96e6603b9ae241f9" sha256: "7ee44229615f8f642b68120165ae4c2a75fe77ae2065b1e55ae4711f6cf0899e"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.24.6" version: "1.25.7"
test_api: test_api:
dependency: transitive dependency: transitive
description: description:
name: test_api name: test_api
sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.6.1" version: "0.7.2"
test_core: test_core:
dependency: transitive dependency: transitive
description: description:
name: test_core name: test_core
sha256: "4bef837e56375537055fdbbbf6dd458b1859881f4c7e6da936158f77d61ab265" sha256: "55ea5a652e38a1dfb32943a7973f3681a60f872f8c3a05a14664ad54ef9c6696"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.5.6" version: "0.6.4"
typed_data: typed_data:
dependency: transitive dependency: transitive
description: description:
@@ -469,10 +490,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: vm_service name: vm_service
sha256: "0fae432c85c4ea880b33b497d32824b97795b04cdaa74d270219572a1f50268d" sha256: "360c4271613beb44db559547d02f8b0dc044741d0eeb9aa6ccdb47e8ec54c63a"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "11.9.0" version: "14.2.3"
watcher: watcher:
dependency: transitive dependency: transitive
description: description:
@@ -481,22 +502,38 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.1.0" version: "1.1.0"
web:
dependency: transitive
description:
name: web
sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27"
url: "https://pub.dev"
source: hosted
version: "0.5.1"
web_socket:
dependency: transitive
description:
name: web_socket
sha256: "24301d8c293ce6fe327ffe6f59d8fd8834735f0ec36e4fd383ec7ff8a64aa078"
url: "https://pub.dev"
source: hosted
version: "0.1.5"
web_socket_channel: web_socket_channel:
dependency: transitive dependency: transitive
description: description:
name: web_socket_channel name: web_socket_channel
sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b sha256: a2d56211ee4d35d9b344d9d4ce60f362e4f5d1aafb988302906bd732bc731276
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.0" version: "3.0.0"
webkit_inspection_protocol: webkit_inspection_protocol:
dependency: transitive dependency: transitive
description: description:
name: webkit_inspection_protocol name: webkit_inspection_protocol
sha256: "67d3a8b6c79e1987d19d848b0892e582dbb0c66c57cc1fef58a177dd2aa2823d" sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.2.0" version: "1.2.1"
yaml: yaml:
dependency: transitive dependency: transitive
description: description:
@@ -506,4 +543,4 @@ packages:
source: hosted source: hosted
version: "3.1.2" version: "3.1.2"
sdks: sdks:
dart: ">=3.0.6 <4.0.0" dart: ">=3.4.0-256.0.dev <4.0.0"
+16 -19
View File
@@ -1,18 +1,17 @@
import 'dart:convert'; import 'dart:convert';
import 'package:dart_jsonwebtoken/dart_jsonwebtoken.dart';
import 'package:fbla_api/fbla_api.dart';
import 'package:test/test.dart';
import 'package:http/http.dart' as http;
import 'dart:io'; import 'dart:io';
final apiAddress = 'https://homelab.marinodev.com'; import 'package:dart_jsonwebtoken/dart_jsonwebtoken.dart';
SecretKey secretKey = SecretKey(Platform.environment['SECRET_KEY']!); import 'package:fbla_api/fbla_api.dart';
import 'package:http/http.dart' as http;
import 'package:test/test.dart';
void main() async{ final apiAddress = 'https://homelab.marinodev.com';
SecretKey secretKey = SecretKey(Platform.environment['JOBLINK_SECRET_KEY']!);
void main() async {
final jwt = JWT( final jwt = JWT(
{ {'username': 'tmp'},
'username': 'tmp'
},
); );
final token = jwt.sign(secretKey); final token = jwt.sign(secretKey);
@@ -43,13 +42,13 @@ void main() async{
"password": "tmp" "password": "tmp"
} }
'''; ''';
var response = await http.post(Uri.parse('$apiAddress, /fbla-api/createuser'), var response = await http.post(Uri.parse('$apiAddress/fbla-api/createuser'),
body: json, body: json,
headers: {'Authorization': token}).timeout(const Duration(seconds: 20)); headers: {'Authorization': token}).timeout(const Duration(seconds: 20));
expect(response.statusCode, 200); expect(response.statusCode, 200);
expect(response.body, 'tmp'); expect(response.body, 'tmp');
}); });
test('sign-in', () async{ test('sign-in', () async {
var json = ''' var json = '''
{ {
"username": "tmp", "username": "tmp",
@@ -64,17 +63,15 @@ void main() async{
expect(response.statusCode, 200); expect(response.statusCode, 200);
expect(JWT.decode(response.body).payload['username'], 'tmp'); expect(JWT.decode(response.body).payload['username'], 'tmp');
}); });
test('delete-user', () async{ test('delete-user', () async {
var json = ''' var json = '''
{ {
"username": "tmp" "username": "tmp"
} }
'''; ''';
var response = await http.post( var response = await http.post(Uri.parse('$apiAddress/fbla-api/deleteuser'),
Uri.parse('$apiAddress/fbla-api/deleteuser'),
body: json, body: json,
headers: {'Authorization': token}).timeout(const Duration(seconds: 20) headers: {'Authorization': token}).timeout(const Duration(seconds: 20));
);
expect(response.statusCode, 200); expect(response.statusCode, 200);
expect(response.body, 'tmp'); expect(response.body, 'tmp');
}); });
@@ -84,7 +81,6 @@ void main() async{
"id": 0, "id": 0,
"name": "tmp", "name": "tmp",
"description": "tmp", "description": "tmp",
"type": "business",
"website": "tmp", "website": "tmp",
"contactName": "tmp", "contactName": "tmp",
"contactEmail": "tmp", "contactEmail": "tmp",
@@ -94,7 +90,8 @@ void main() async{
"locationAddress": "tmp" "locationAddress": "tmp"
} }
'''; ''';
var response = await http.post(Uri.parse('$apiAddress/fbla-api/createbusiness'), var response = await http.post(
Uri.parse('$apiAddress/fbla-api/createbusiness'),
body: json, body: json,
headers: {'Authorization': token}).timeout(const Duration(seconds: 20)); headers: {'Authorization': token}).timeout(const Duration(seconds: 20));
+17
View File
@@ -6,6 +6,8 @@ My version of the app can be found at [marinodev.com/fbla/](https://marinodev.co
Pre-built files for several operating systems (built with my API) can be found in the releases tab, Pre-built files for several operating systems (built with my API) can be found in the releases tab,
alternatively, you can compile it yourself for use with your own API and database (see API readme): alternatively, you can compile it yourself for use with your own API and database (see API readme):
### Windows/Linux
1. Install [Flutter](https://docs.flutter.dev/get-started/install) 1. Install [Flutter](https://docs.flutter.dev/get-started/install)
2. Use `flutter doctor` to make sure your environment is fully set up for your platform 2. Use `flutter doctor` to make sure your environment is fully set up for your platform
3. Clone the repo 3. Clone the repo
@@ -18,3 +20,18 @@ cd FBLA24/fbla_ui/
4. Run `flutter pub get` to install all dependencies 4. Run `flutter pub get` to install all dependencies
5. Optional: set `apiAddress` at the top of `lib/api_logic.dart` 5. Optional: set `apiAddress` at the top of `lib/api_logic.dart`
6. Build app with `flutter build --release` 6. Build app with `flutter build --release`
### MacOS
*These instructions are temporary and will change as I try MacOS*
1. Install [Flutter](https://docs.flutter.dev/get-started/install)
2. Use `flutter doctor` to make sure your environment is fully set up for your platform
3. Clone the repo
```
git clone https://git.marinodev.com/MarinoDev/FBLA24.git
cd FBLA24/fbla_ui/
```
4. Run `flutter pub get` to install all dependencies
5. Optional: set `apiAddress` at the top of `lib/api_logic.dart`
6. Build app with `flutter build --release`
+50 -2
View File
@@ -26,6 +26,7 @@ class _CreateBusinessDetailState extends State<BusinessDetail> {
), ),
body: ListView( body: ListView(
children: [ children: [
// Title, logo, desc, website
Card( Card(
clipBehavior: Clip.antiAlias, clipBehavior: Clip.antiAlias,
child: Column( child: Column(
@@ -41,8 +42,7 @@ class _CreateBusinessDetailState extends State<BusinessDetail> {
), ),
leading: ClipRRect( leading: ClipRRect(
borderRadius: BorderRadius.circular(6.0), borderRadius: BorderRadius.circular(6.0),
child: Image.network( child: Image.network('$apiAddress/logos/${business.id}',
'$apiAddress/logos/${business.id}',
width: 48, width: 48,
height: 48, errorBuilder: (BuildContext context, height: 48, errorBuilder: (BuildContext context,
Object exception, StackTrace? stackTrace) { Object exception, StackTrace? stackTrace) {
@@ -63,6 +63,52 @@ class _CreateBusinessDetailState extends State<BusinessDetail> {
], ],
), ),
), ),
// Available positions
Card(
child: Padding(
padding: const EdgeInsets.only(left: 16.0, top: 8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Available Postitions',
style: const TextStyle(
fontSize: 20, fontWeight: FontWeight.bold),
),
// Container(
// height: 400,
// width: 300,
ListView(
scrollDirection: Axis.vertical,
shrinkWrap: true,
children: [
ListTile(
title: Text('Postition 1'),
leading: Icon(Icons.work),
onTap: () {
// launchUrl(Uri.parse(''));
},
),
ListTile(
title: Text('Postition 2'),
leading: Icon(Icons.work),
onTap: () {
// launchUrl(Uri.parse(''));
},
),
ListTile(
title: Text('Postition 3'),
leading: Icon(Icons.work),
onTap: () {
// launchUrl(Uri.parse(''));
},
),
],
),
]),
),
),
// Contact info
Visibility( Visibility(
visible: (business.contactEmail.isNotEmpty || visible: (business.contactEmail.isNotEmpty ||
business.contactPhone.isNotEmpty), business.contactPhone.isNotEmpty),
@@ -138,6 +184,7 @@ class _CreateBusinessDetailState extends State<BusinessDetail> {
), ),
), ),
), ),
// Location
Visibility( Visibility(
child: Card( child: Card(
clipBehavior: Clip.antiAlias, clipBehavior: Clip.antiAlias,
@@ -152,6 +199,7 @@ class _CreateBusinessDetailState extends State<BusinessDetail> {
), ),
), ),
), ),
// Notes
Visibility( Visibility(
visible: business.notes.isNotEmpty, visible: business.notes.isNotEmpty,
child: Card( child: Card(
+11 -11
View File
@@ -17,22 +17,22 @@ cmake_policy(SET CMP0063 NEW)
set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")
# Root filesystem for cross-building. # Root filesystem for cross-building.
if(FLUTTER_TARGET_PLATFORM_SYSROOT) if (FLUTTER_TARGET_PLATFORM_SYSROOT)
set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT})
set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
endif() endif ()
# Define build configuration options. # Define build configuration options.
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE "Debug" CACHE set(CMAKE_BUILD_TYPE "Debug" CACHE
STRING "Flutter build mode" FORCE) STRING "Flutter build mode" FORCE)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
"Debug" "Profile" "Release") "Debug" "Profile" "Release")
endif() endif ()
# Compilation settings that should be applied to most targets. # Compilation settings that should be applied to most targets.
# #
@@ -41,7 +41,7 @@ endif()
# of modifying this function. # of modifying this function.
function(APPLY_STANDARD_SETTINGS TARGET) function(APPLY_STANDARD_SETTINGS TARGET)
target_compile_features(${TARGET} PUBLIC cxx_std_14) target_compile_features(${TARGET} PUBLIC cxx_std_14)
target_compile_options(${TARGET} PRIVATE -Wall -Werror) target_compile_options(${TARGET} PRIVATE -Wall) # removed -Werror to avoid error from libraries on unused vars
target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>") target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>")
target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>") target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>")
endfunction() endfunction()
@@ -96,9 +96,9 @@ include(flutter/generated_plugins.cmake)
# By default, "installing" just makes a relocatable bundle in the build # By default, "installing" just makes a relocatable bundle in the build
# directory. # directory.
set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle")
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
endif() endif ()
# Start with a clean build bundle directory every time. # Start with a clean build bundle directory every time.
install(CODE " install(CODE "
@@ -117,11 +117,11 @@ install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}
install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime) COMPONENT Runtime)
foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) foreach (bundled_library ${PLUGIN_BUNDLED_LIBRARIES})
install(FILES "${bundled_library}" install(FILES "${bundled_library}"
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime) COMPONENT Runtime)
endforeach(bundled_library) endforeach (bundled_library)
# Fully re-copy the assets directory on each build to avoid having stale files # Fully re-copy the assets directory on each build to avoid having stale files
# from a previous install. # from a previous install.
@@ -133,7 +133,7 @@ install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
# Install the AOT library on non-Debug builds only. # Install the AOT library on non-Debug builds only.
if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") if (NOT CMAKE_BUILD_TYPE MATCHES "Debug")
install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime) COMPONENT Runtime)
endif() endif ()
@@ -7,12 +7,16 @@
#include "generated_plugin_registrant.h" #include "generated_plugin_registrant.h"
#include <printing/printing_plugin.h> #include <printing/printing_plugin.h>
#include <rive_common/rive_plugin.h>
#include <url_launcher_linux/url_launcher_plugin.h> #include <url_launcher_linux/url_launcher_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) { void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) printing_registrar = g_autoptr(FlPluginRegistrar) printing_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "PrintingPlugin"); fl_plugin_registry_get_registrar_for_plugin(registry, "PrintingPlugin");
printing_plugin_register_with_registrar(printing_registrar); printing_plugin_register_with_registrar(printing_registrar);
g_autoptr(FlPluginRegistrar) rive_common_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "RivePlugin");
rive_plugin_register_with_registrar(rive_common_registrar);
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
@@ -4,6 +4,7 @@
list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_PLUGIN_LIST
printing printing
rive_common
url_launcher_linux url_launcher_linux
) )
+56 -56
View File
@@ -13,10 +13,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: archive name: archive
sha256: "22600aa1e926be775fa5fe7e6894e7fb3df9efda8891c73f70fb3262399a432d" sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.4.10" version: "3.6.1"
async: async:
dependency: transitive dependency: transitive
description: description:
@@ -29,10 +29,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: barcode name: barcode
sha256: "91b143666f7bb13636f716b6d4e412e372ab15ff7969799af8c9e30a382e9385" sha256: ab180ce22c6555d77d45f0178a523669db67f95856e3378259ef2ffeb43e6003
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.6" version: "2.2.8"
bidi: bidi:
dependency: transitive dependency: transitive
description: description:
@@ -93,18 +93,18 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: cupertino_icons name: cupertino_icons
sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.6" version: "1.0.8"
dart_jsonwebtoken: dart_jsonwebtoken:
dependency: "direct main" dependency: "direct main"
description: description:
name: dart_jsonwebtoken name: dart_jsonwebtoken
sha256: "40dc3a4788c02a44bc97ea0c8c4a078ae58c9a45acc2312ee6a689b0e8f5b5b9" sha256: "346e9a21e4bf6e6a431e19ece00ebb2e3668e1e339cabdf6f46d18d88692a848"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.13.0" version: "2.14.0"
ed25519_edwards: ed25519_edwards:
dependency: transitive dependency: transitive
description: description:
@@ -204,10 +204,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: image name: image
sha256: "4c68bfd5ae83e700b5204c1e74451e7bf3cf750e6843c6e158289cf56bda018e" sha256: "2237616a36c0d69aef7549ab439b833fb7f9fb9fc861af2cc9ac3eedddd69ca8"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.1.7" version: "4.2.0"
js: js:
dependency: transitive dependency: transitive
description: description:
@@ -220,26 +220,26 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: leak_tracker name: leak_tracker
sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "10.0.0" version: "10.0.4"
leak_tracker_flutter_testing: leak_tracker_flutter_testing:
dependency: transitive dependency: transitive
description: description:
name: leak_tracker_flutter_testing name: leak_tracker_flutter_testing
sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.1" version: "3.0.3"
leak_tracker_testing: leak_tracker_testing:
dependency: transitive dependency: transitive
description: description:
name: leak_tracker_testing name: leak_tracker_testing
sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.1" version: "3.0.1"
lints: lints:
dependency: transitive dependency: transitive
description: description:
@@ -268,10 +268,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: meta name: meta
sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.11.0" version: "1.12.0"
open_filex: open_filex:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -300,26 +300,26 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: path_provider name: path_provider
sha256: b27217933eeeba8ff24845c34003b003b2b22151de3c908d0e679e8fe1aa078b sha256: c9e7d3a4cd1410877472158bee69963a4579f78b68c65a2b7d40d1a7a88bb161
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.2" version: "2.1.3"
path_provider_android: path_provider_android:
dependency: transitive dependency: transitive
description: description:
name: path_provider_android name: path_provider_android
sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668" sha256: "9c96da072b421e98183f9ea7464898428e764bc0ce5567f27ec8693442e72514"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.2" version: "2.2.5"
path_provider_foundation: path_provider_foundation:
dependency: transitive dependency: transitive
description: description:
name: path_provider_foundation name: path_provider_foundation
sha256: "5a7999be66e000916500be4f15a3633ebceb8302719b47b9cc49ce924125350f" sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.2" version: "2.4.0"
path_provider_linux: path_provider_linux:
dependency: transitive dependency: transitive
description: description:
@@ -356,10 +356,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: pdf_widget_wrapper name: pdf_widget_wrapper
sha256: "9c3ca36e5000c9682d52bbdc486867ba7c5ee4403d1a5d6d03ed72157753377b" sha256: c930860d987213a3d58c7ec3b7ecf8085c3897f773e8dc23da9cae60a5d6d0f5
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.3" version: "1.0.4"
petitparser: petitparser:
dependency: transitive dependency: transitive
description: description:
@@ -388,10 +388,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: pointycastle name: pointycastle
sha256: "43ac87de6e10afabc85c445745a7b799e04de84cebaa4fd7bf55a5e1e9604d29" sha256: "4be0097fcf3fd3e8449e53730c631200ebc7b88016acecab2b0da2f0149222fe"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.7.4" version: "3.9.1"
printing: printing:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -412,42 +412,42 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: rive name: rive
sha256: ec44b6cf7341e21727c4b0e762f4ac82f9a45f7e52df3ebad2d1289a726fbaaf sha256: "03bae056e67a5c98f9523c34f8ea63c15b323426a7e8d76d7ebb93066d4df6dc"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.13.1" version: "0.13.5"
rive_common: rive_common:
dependency: transitive dependency: transitive
description: description:
name: rive_common name: rive_common
sha256: "0f070bc0e764c570abd8b34d744ef30d1292bd4051f2e0951bbda755875fce6a" sha256: "3fe76ba4680787741688ee393e47b63417e8643816795e4eac01021683af1d84"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.3.3" version: "0.4.9"
shared_preferences: shared_preferences:
dependency: "direct main" dependency: "direct main"
description: description:
name: shared_preferences name: shared_preferences
sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02" sha256: d3bbe5553a986e83980916ded2f0b435ef2e1893dfaa29d5a7a790d0eca12180
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.2" version: "2.2.3"
shared_preferences_android: shared_preferences_android:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_android name: shared_preferences_android
sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06" sha256: "93d0ec9dd902d85f326068e6a899487d1f65ffcd5798721a95330b26c8131577"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.1" version: "2.2.3"
shared_preferences_foundation: shared_preferences_foundation:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_foundation name: shared_preferences_foundation
sha256: "7708d83064f38060c7b39db12aefe449cb8cdc031d6062280087bc4cdb988f5c" sha256: "0a8a893bf4fd1152f93fec03a415d11c27c74454d96e2318a7ac38dd18683ab7"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.5" version: "2.4.0"
shared_preferences_linux: shared_preferences_linux:
dependency: transitive dependency: transitive
description: description:
@@ -537,10 +537,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: test_api name: test_api
sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.6.1" version: "0.7.0"
typed_data: typed_data:
dependency: transitive dependency: transitive
description: description:
@@ -553,26 +553,26 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: url_launcher name: url_launcher
sha256: "0ecc004c62fd3ed36a2ffcbe0dd9700aee63bd7532d0b642a488b1ec310f492e" sha256: "21b704ce5fa560ea9f3b525b43601c678728ba46725bab9b01187b4831377ed3"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.2.5" version: "6.3.0"
url_launcher_android: url_launcher_android:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_android name: url_launcher_android
sha256: d4ed0711849dd8e33eb2dd69c25db0d0d3fdc37e0a62e629fe32f57a22db2745 sha256: ceb2625f0c24ade6ef6778d1de0b2e44f2db71fded235eb52295247feba8c5cf
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.3.0" version: "6.3.3"
url_launcher_ios: url_launcher_ios:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_ios name: url_launcher_ios
sha256: "9149d493b075ed740901f3ee844a38a00b33116c7c5c10d7fb27df8987fb51d5" sha256: "7068716403343f6ba4969b4173cbf3b84fc768042124bc2c011e5d782b24fe89"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.2.5" version: "6.3.0"
url_launcher_linux: url_launcher_linux:
dependency: transitive dependency: transitive
description: description:
@@ -585,10 +585,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_macos name: url_launcher_macos
sha256: b7244901ea3cf489c5335bdacda07264a6e960b1c1b1a9f91e4bc371d9e68234 sha256: "9a1a42d5d2d95400c795b2914c36fdcb525870c752569438e4ebb09a2b5d90de"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.0" version: "3.2.0"
url_launcher_platform_interface: url_launcher_platform_interface:
dependency: transitive dependency: transitive
description: description:
@@ -601,10 +601,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_web name: url_launcher_web
sha256: "3692a459204a33e04bc94f5fb91158faf4f2c8903281ddd82915adecdb1a901d" sha256: "8d9e750d8c9338601e709cd0885f95825086bd8b642547f26bda435aade95d8a"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.0" version: "2.3.1"
url_launcher_windows: url_launcher_windows:
dependency: transitive dependency: transitive
description: description:
@@ -633,10 +633,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: vm_service name: vm_service
sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "13.0.0" version: "14.2.1"
web: web:
dependency: transitive dependency: transitive
description: description:
@@ -649,10 +649,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: win32 name: win32
sha256: "8cb58b45c47dcb42ab3651533626161d6b67a2921917d8d429791f76972b3480" sha256: a79dbe579cb51ecd6d30b17e0cae4e0ea15e2c0e66f69ad4198f22a6789e94f4
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.3.0" version: "5.5.1"
xdg_directories: xdg_directories:
dependency: transitive dependency: transitive
description: description:
@@ -670,5 +670,5 @@ packages:
source: hosted source: hosted
version: "6.5.0" version: "6.5.0"
sdks: sdks:
dart: ">=3.3.0 <4.0.0" dart: ">=3.4.0 <4.0.0"
flutter: ">=3.19.0" flutter: ">=3.22.0"